summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--UPGRADING5
-rw-r--r--Zend/zend_portability.h2
-rw-r--r--ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c2
-rw-r--r--ext/mbstring/mbstring.c3
-rw-r--r--ext/mysqlnd/mysqlnd_connection.c40
-rw-r--r--ext/mysqlnd/mysqlnd_connection.h5
-rw-r--r--ext/mysqlnd/mysqlnd_structs.h4
-rw-r--r--ext/opcache/Optimizer/dfa_pass.c8
-rw-r--r--ext/opcache/Optimizer/zend_cfg.c32
-rw-r--r--ext/opcache/Optimizer/zend_dump.c13
-rw-r--r--ext/opcache/Optimizer/zend_func_info.h2
-rw-r--r--ext/opcache/Optimizer/zend_inference.c34
-rw-r--r--ext/opcache/Optimizer/zend_ssa.c76
-rw-r--r--ext/opcache/Optimizer/zend_ssa.h7
-rw-r--r--ext/readline/config.w3216
-rw-r--r--ext/readline/php_readline.h2
-rw-r--r--ext/readline/readline.c8
-rw-r--r--ext/readline/readline_cli.c37
-rw-r--r--ext/readline/tests/libedit_info_001-win32.phpt42
-rw-r--r--ext/readline/tests/libedit_info_001.phpt3
-rw-r--r--ext/readline/tests/libedit_write_history_001-win32.phpt29
-rw-r--r--ext/readline/tests/libedit_write_history_001.phpt3
-rw-r--r--ext/session/mod_user.c11
-rw-r--r--ext/session/mod_user_class.c27
-rw-r--r--ext/session/session.c53
-rw-r--r--ext/session/tests/bug55688.phpt2
-rw-r--r--ext/session/tests/bug60634.phpt9
-rw-r--r--ext/session/tests/bug60634_error_1.phpt6
-rw-r--r--ext/session/tests/bug67972.phpt3
-rw-r--r--ext/session/tests/bug68063.phpt14
-rw-r--r--ext/session/tests/bug69111.phpt36
-rw-r--r--ext/session/tests/bug70133.phpt41
-rw-r--r--ext/session/tests/sessionhandler_open_001.phpt7
-rw-r--r--ext/soap/soap.c2
-rw-r--r--ext/sockets/tests/socket_clear_error-win32.phpt32
-rw-r--r--ext/sockets/tests/socket_clear_error.phpt3
-rw-r--r--ext/sockets/tests/socket_send.phpt3
-rw-r--r--ext/sockets/tests/socket_send_win32.phpt43
-rw-r--r--ext/sockets/tests/socket_shutdown-win32.phpt59
-rw-r--r--ext/sockets/tests/socket_shutdown.phpt3
-rw-r--r--ext/standard/math.c12
-rw-r--r--ext/standard/tests/streams/stream_socket_enable_crypto-win32.phpt69
-rw-r--r--ext/standard/tests/streams/stream_socket_enable_crypto.phpt3
-rw-r--r--sapi/cgi/cgi_main.c89
-rw-r--r--sapi/cli/config.w325
-rw-r--r--sapi/cli/tests/cli_process_title_windows.phpt10
-rw-r--r--win32/build/confutils.js9
47 files changed, 798 insertions, 126 deletions
diff --git a/UPGRADING b/UPGRADING
index f4c4765c4a..344c221273 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -95,6 +95,11 @@ PHP 7.1 UPGRADE NOTES
- Core:
. Support for ftok()
+- FCGI
+ . PHP_FCGI_CHILDREN is respected. If this environment variable is defined,
+ the first php-fcgi.exe process will exec the specified number of children.
+ Those will share the same TCP socket.
+
========================================
13. Other Changes
========================================
diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h
index f187129416..298dfb53fa 100644
--- a/Zend/zend_portability.h
+++ b/Zend/zend_portability.h
@@ -284,7 +284,7 @@ char *alloca();
# endif
# elif defined(_MSC_VER)
# define zend_always_inline __forceinline
-# define zend_never_inline
+# define zend_never_inline __declspec(noinline)
# else
# if __has_attribute(always_inline)
# define zend_always_inline inline __attribute__((always_inline))
diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c b/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c
index 77736a051b..75d249fbe8 100644
--- a/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c
+++ b/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c
@@ -278,7 +278,7 @@ retry:
w = cp932ext1_ucs_table[s - cp932ext1_ucs_table_min];
} else if (s >= cp932ext2_ucs_table_min && s < cp932ext2_ucs_table_max) {
w = cp932ext2_ucs_table[s - cp932ext2_ucs_table_min];
- } else if (s >= cp932ext3_ucs_table_min && s < cp932ext2_ucs_table_max) {
+ } else if (s >= cp932ext3_ucs_table_min && s < cp932ext3_ucs_table_max) {
w = cp932ext3_ucs_table[s - cp932ext3_ucs_table_min];
} else if (s >= 94 * 94 && s < 114 * 94) {
/* user-defined => PUA (Microsoft extended) */
diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c
index 4fdb3d5b2e..b5812cb402 100644
--- a/ext/mbstring/mbstring.c
+++ b/ext/mbstring/mbstring.c
@@ -4145,9 +4145,10 @@ PHP_FUNCTION(mb_send_mail)
suppressed_hdrs.cnt_type = 1;
}
- if ((s = zend_hash_str_find_ptr(&ht_headers, "CONTENT-TRANSFER-ENCODING", sizeof("CONTENT-TRANSFER-ENCODING") - 1))) {
+ if ((s = zend_hash_str_find(&ht_headers, "CONTENT-TRANSFER-ENCODING", sizeof("CONTENT-TRANSFER-ENCODING") - 1))) {
enum mbfl_no_encoding _body_enc;
+ ZEND_ASSERT(Z_TYPE_P(s) == IS_STRING);
_body_enc = mbfl_name2no_encoding(Z_STRVAL_P(s));
switch (_body_enc) {
case mbfl_no_encoding_base64:
diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c
index 2cefe755d8..6f350cfd79 100644
--- a/ext/mysqlnd/mysqlnd_connection.c
+++ b/ext/mysqlnd/mysqlnd_connection.c
@@ -40,7 +40,7 @@ PHPAPI const char * const mysqlnd_server_gone = "MySQL server has gone away";
PHPAPI const char * const mysqlnd_out_of_sync = "Commands out of sync; you can't run this command now";
PHPAPI const char * const mysqlnd_out_of_memory = "Out of memory";
-PHPAPI MYSQLND_STATS *mysqlnd_global_stats = NULL;
+PHPAPI MYSQLND_STATS * mysqlnd_global_stats = NULL;
/* {{{ mysqlnd_upsert_status::reset */
@@ -152,8 +152,8 @@ MYSQLND_CLASS_METHODS_END;
/* {{{ mysqlnd_error_info_init */
-enum_func_status
-mysqlnd_error_info_init(MYSQLND_ERROR_INFO * const info, zend_bool persistent)
+PHPAPI enum_func_status
+mysqlnd_error_info_init(MYSQLND_ERROR_INFO * const info, const zend_bool persistent)
{
DBG_ENTER("mysqlnd_error_info_init");
info->m = mysqlnd_error_info_get_methods();
@@ -163,12 +163,28 @@ mysqlnd_error_info_init(MYSQLND_ERROR_INFO * const info, zend_bool persistent)
if (info->error_list) {
zend_llist_init(info->error_list, sizeof(MYSQLND_ERROR_LIST_ELEMENT), (llist_dtor_func_t) mysqlnd_error_list_pdtor, persistent);
}
-
+ info->persistent = persistent;
DBG_RETURN(info->error_list? PASS:FAIL);
}
/* }}} */
+/* {{{ mysqlnd_error_info_free_contents */
+PHPAPI void
+mysqlnd_error_info_free_contents(MYSQLND_ERROR_INFO * const info)
+{
+ DBG_ENTER("mysqlnd_error_info_free_contents");
+ info->m->reset(info);
+ if (info->error_list) {
+ mnd_pefree(info->error_list, info->persistent);
+ info->error_list = NULL;
+ }
+
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
/* {{{ mysqlnd_connection_state::get */
@@ -200,10 +216,8 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_connection_state)
MYSQLND_CLASS_METHODS_END;
-
-
/* {{{ mysqlnd_upsert_status_init */
-void
+PHPAPI void
mysqlnd_connection_state_init(struct st_mysqlnd_connection_state * const state)
{
DBG_ENTER("mysqlnd_error_info_init");
@@ -214,6 +228,7 @@ mysqlnd_connection_state_init(struct st_mysqlnd_connection_state * const state)
/* }}} */
+
/* {{{ mysqlnd_conn_data::free_options */
static void
MYSQLND_METHOD(mysqlnd_conn_data, free_options)(MYSQLND_CONN_DATA * conn)
@@ -318,11 +333,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, free_contents)(MYSQLND_CONN_DATA * conn)
mnd_pefree(conn->last_message.s, pers);
conn->last_message.s = NULL;
}
- if (conn->error_info->error_list) {
- zend_llist_clean(conn->error_info->error_list);
- mnd_pefree(conn->error_info->error_list, pers);
- conn->error_info->error_list = NULL;
- }
+
conn->charset = NULL;
conn->greet_charset = NULL;
@@ -341,6 +352,11 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, dtor)(MYSQLND_CONN_DATA * conn)
conn->m->free_contents(conn);
conn->m->free_options(conn);
+ if (conn->error_info) {
+ mysqlnd_error_info_free_contents(conn->error_info);
+ conn->error_info = NULL;
+ }
+
if (conn->protocol_frame_codec) {
mysqlnd_pfc_free(conn->protocol_frame_codec, conn->stats, conn->error_info);
conn->protocol_frame_codec = NULL;
diff --git a/ext/mysqlnd/mysqlnd_connection.h b/ext/mysqlnd/mysqlnd_connection.h
index cdffe594d9..0668d09d92 100644
--- a/ext/mysqlnd/mysqlnd_connection.h
+++ b/ext/mysqlnd/mysqlnd_connection.h
@@ -67,12 +67,13 @@ void mysqlnd_upsert_status_init(MYSQLND_UPSERT_STATUS * const upsert_status);
}
-enum_func_status mysqlnd_error_info_init(MYSQLND_ERROR_INFO * const info, zend_bool persistent);
+PHPAPI enum_func_status mysqlnd_error_info_init(MYSQLND_ERROR_INFO * const info, const zend_bool persistent);
+PHPAPI void mysqlnd_error_info_free_contents(MYSQLND_ERROR_INFO * const info);
#define GET_CONNECTION_STATE(state_struct) (state_struct)->m->get((state_struct))
#define SET_CONNECTION_STATE(state_struct, s) (state_struct)->m->set((state_struct), (s))
-void mysqlnd_connection_state_init(struct st_mysqlnd_connection_state * const state);
+PHPAPI void mysqlnd_connection_state_init(struct st_mysqlnd_connection_state * const state);
#endif /* MYSQLND_CONNECTION_H */
diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h
index 35a0f3b16c..cc5e2b7ac4 100644
--- a/ext/mysqlnd/mysqlnd_structs.h
+++ b/ext/mysqlnd/mysqlnd_structs.h
@@ -32,6 +32,9 @@
#define MYSQLND_CLASS_METHODS_START(class) MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(class) = {
#define MYSQLND_CLASS_METHODS_END }
+#define MYSQLND_CLASS_METHODS_INSTANCE_NAME(class) mysqlnd_##class##_methods_ptr
+#define MYSQLND_CLASS_METHODS_INSTANCE_DECLARE(class) extern const MYSQLND_CLASS_METHODS_TYPE(class) * MYSQLND_CLASS_METHODS_INSTANCE_NAME(class)
+#define MYSQLND_CLASS_METHODS_INSTANCE_DEFINE(class) const MYSQLND_CLASS_METHODS_TYPE(class) * MYSQLND_CLASS_METHODS_INSTANCE_NAME(class) = & MYSQLND_CLASS_METHOD_TABLE_NAME(class)
typedef struct st_mysqlnd_string
{
@@ -154,6 +157,7 @@ struct st_mysqlnd_error_info
unsigned int error_no;
zend_llist * error_list;
+ zend_bool persistent;
MYSQLND_CLASS_METHODS_TYPE(mysqlnd_error_info) *m;
};
diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c
index a1872e3d81..02dfdd5b7e 100644
--- a/ext/opcache/Optimizer/dfa_pass.c
+++ b/ext/opcache/Optimizer/dfa_pass.c
@@ -34,6 +34,11 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx,
{
uint32_t build_flags;
+ if (op_array->last_try_catch) {
+ /* TODO: we can't analyze functions with try/catch/finally ??? */
+ return FAILURE;
+ }
+
/* Build SSA */
memset(ssa, 0, sizeof(zend_ssa));
@@ -41,7 +46,8 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx,
return FAILURE;
}
- if (*flags & ZEND_FUNC_TOO_DYNAMIC) {
+ if (*flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) {
+ /* TODO: we can't analyze functions with indirect variable access ??? */
return FAILURE;
}
diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c
index 728d586026..b8121808d2 100644
--- a/ext/opcache/Optimizer/zend_cfg.c
+++ b/ext/opcache/Optimizer/zend_cfg.c
@@ -251,10 +251,6 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
/* Build CFG, Step 1: Find basic blocks starts, calculate number of blocks */
BB_START(0);
- if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->static_variables) {
- // FIXME: Really we should try to perform variable initialization
- flags |= ZEND_FUNC_TOO_DYNAMIC;
- }
for (i = 0; i < op_array->last; i++) {
zend_op *opline = op_array->opcodes + i;
switch(opline->opcode) {
@@ -268,9 +264,9 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
}
break;
case ZEND_INCLUDE_OR_EVAL:
+ flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
case ZEND_YIELD:
case ZEND_YIELD_FROM:
- flags |= ZEND_FUNC_TOO_DYNAMIC;
if (build_flags & ZEND_CFG_STACKLESS) {
BB_START(i + 1);
}
@@ -296,15 +292,17 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
if ((fn = zend_hash_find_ptr(EG(function_table), Z_STR_P(zv))) != NULL) {
if (fn->type == ZEND_INTERNAL_FUNCTION) {
if (zend_string_equals_literal(Z_STR_P(zv), "extract")) {
- flags |= ZEND_FUNC_TOO_DYNAMIC;
+ flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
} else if (zend_string_equals_literal(Z_STR_P(zv), "compact")) {
- flags |= ZEND_FUNC_TOO_DYNAMIC;
- } else if (zend_string_equals_literal(Z_STR_P(zv), "parse_str")) {
- flags |= ZEND_FUNC_TOO_DYNAMIC;
- } else if (zend_string_equals_literal(Z_STR_P(zv), "mb_parse_str")) {
- flags |= ZEND_FUNC_TOO_DYNAMIC;
+ flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
+ } else if (zend_string_equals_literal(Z_STR_P(zv), "parse_str") &&
+ opline->extended_value == 1) {
+ flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
+ } else if (zend_string_equals_literal(Z_STR_P(zv), "mb_parse_str") &&
+ opline->extended_value == 1) {
+ flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
} else if (zend_string_equals_literal(Z_STR_P(zv), "get_defined_vars")) {
- flags |= ZEND_FUNC_TOO_DYNAMIC;
+ flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
} else if (zend_string_equals_literal(Z_STR_P(zv), "func_num_args")) {
flags |= ZEND_FUNC_VARARG;
} else if (zend_string_equals_literal(Z_STR_P(zv), "func_get_arg")) {
@@ -316,12 +314,10 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
}
break;
case ZEND_FAST_CALL:
- flags |= ZEND_FUNC_TOO_DYNAMIC;
BB_START(OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes);
BB_START(i + 1);
break;
case ZEND_FAST_RET:
- flags |= ZEND_FUNC_TOO_DYNAMIC;
if (i + 1 < op_array->last) {
BB_START(i + 1);
}
@@ -350,7 +346,6 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
BB_START(i + 1);
break;
case ZEND_CATCH:
- flags |= ZEND_FUNC_TOO_DYNAMIC;
if (!opline->result.num) {
BB_START(ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
}
@@ -370,8 +365,9 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
BB_START(i + 1);
break;
case ZEND_UNSET_VAR:
+ case ZEND_ISSET_ISEMPTY_VAR:
if (!(opline->extended_value & ZEND_QUICK_SET)) {
- flags |= ZEND_FUNC_TOO_DYNAMIC;
+ flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
}
break;
case ZEND_FETCH_R:
@@ -381,11 +377,11 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
case ZEND_FETCH_IS:
case ZEND_FETCH_UNSET:
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_LOCAL) {
- flags |= ZEND_FUNC_TOO_DYNAMIC;
+ flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
} else if (((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL ||
(opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL_LOCK) &&
!op_array->function_name) {
- flags |= ZEND_FUNC_TOO_DYNAMIC;
+ flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
}
break;
}
diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c
index 53458644fc..46952c1159 100644
--- a/ext/opcache/Optimizer/zend_dump.c
+++ b/ext/opcache/Optimizer/zend_dump.c
@@ -305,8 +305,14 @@ void zend_dump_ssa_var(const zend_op_array *op_array, const zend_ssa *ssa, int s
}
}
-static void zend_dump_pi_range(const zend_op_array *op_array, const zend_ssa *ssa, const zend_ssa_pi_range *r)
+static void zend_dump_pi_constraint(const zend_op_array *op_array, const zend_ssa *ssa, const zend_ssa_pi_constraint *r)
{
+ if (r->type_mask != (uint32_t) -1) {
+ fprintf(stderr, " TYPE");
+ zend_dump_type_info(r->type_mask, NULL, 0);
+ return;
+ }
+
if (r->range.underflow && r->range.overflow) {
return;
}
@@ -791,7 +797,7 @@ static void zend_dump_block_header(const zend_cfg *cfg, const zend_op_array *op_
fprintf(stderr, " = Pi(");
zend_dump_ssa_var(op_array, ssa, p->sources[0], 0, p->var);
fprintf(stderr, " &");
- zend_dump_pi_range(op_array, ssa, &p->constraint);
+ zend_dump_pi_constraint(op_array, ssa, &p->constraint);
fprintf(stderr, ")\n");
}
p = p->next;
@@ -853,6 +859,9 @@ void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, cons
if (ssa) {
fprintf(stderr, ", ssa_vars=%d", ssa->vars_count);
}
+ if (func_flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) {
+ fprintf(stderr, ", dynamic");
+ }
if (func_flags & ZEND_FUNC_RECURSIVE) {
fprintf(stderr, ", recursive");
if (func_flags & ZEND_FUNC_RECURSIVE_DIRECTLY) {
diff --git a/ext/opcache/Optimizer/zend_func_info.h b/ext/opcache/Optimizer/zend_func_info.h
index 4b0aadd4ee..8fcf00d26a 100644
--- a/ext/opcache/Optimizer/zend_func_info.h
+++ b/ext/opcache/Optimizer/zend_func_info.h
@@ -22,7 +22,7 @@
#include "zend_ssa.h"
/* func flags */
-#define ZEND_FUNC_TOO_DYNAMIC (1<<0)
+#define ZEND_FUNC_INDIRECT_VAR_ACCESS (1<<0)
#define ZEND_FUNC_HAS_CALLS (1<<1)
#define ZEND_FUNC_VARARG (1<<2)
#define ZEND_FUNC_NO_LOOPS (1<<3)
diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c
index 41bd4eebb0..beec91924c 100644
--- a/ext/opcache/Optimizer/zend_inference.c
+++ b/ext/opcache/Optimizer/zend_inference.c
@@ -475,7 +475,7 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int
tmp->min = ZEND_LONG_MAX;
tmp->max = ZEND_LONG_MIN;
tmp->overflow = 0;
- if (p->pi >= 0) {
+ if (p->pi >= 0 && p->constraint.type_mask == (uint32_t) -1) {
if (p->constraint.negative) {
if (ssa->var_info[p->sources[0]].has_range) {
tmp->underflow = ssa->var_info[p->sources[0]].range.underflow;
@@ -1814,6 +1814,7 @@ static void zend_infer_ranges_warmup(const zend_op_array *op_array, zend_ssa *ss
ssa->var_info[j].has_range &&
ssa->vars[j].definition_phi &&
ssa->vars[j].definition_phi->pi >= 0 &&
+ ssa->vars[j].definition_phi->constraint.type_mask == (uint32_t) -1 &&
ssa->vars[j].definition_phi->constraint.negative &&
ssa->vars[j].definition_phi->constraint.min_ssa_var < 0 &&
ssa->vars[j].definition_phi->constraint.min_ssa_var < 0) {
@@ -3067,8 +3068,11 @@ static void zend_update_type_info(const zend_op_array *op_array,
}
break;
case ZEND_BIND_GLOBAL:
+ tmp = (MAY_BE_REF | MAY_BE_ANY);
+ UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
+ break;
case ZEND_BIND_STATIC:
- tmp = (MAY_BE_REF | MAY_BE_ANY );
+ tmp = MAY_BE_ANY | (opline->extended_value ? MAY_BE_REF : (MAY_BE_RC1 | MAY_BE_RCN));
UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
break;
case ZEND_SEND_VAR:
@@ -3655,6 +3659,9 @@ int zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script
zend_ssa_phi *p = ssa_vars[j].definition_phi;
if (p->pi >= 0) {
tmp = get_ssa_var_info(ssa, p->sources[0]);
+ if (p->constraint.type_mask != (uint32_t) -1) {
+ tmp &= p->constraint.type_mask;
+ }
UPDATE_SSA_TYPE(tmp, j);
if (ssa_var_info[p->sources[0]].ce) {
UPDATE_SSA_OBJ_TYPE(ssa_var_info[p->sources[0]].ce, ssa_var_info[p->sources[0]].is_instanceof, j);
@@ -4071,17 +4078,22 @@ int zend_ssa_inference(zend_arena **arena, const zend_op_array *op_array, const
}
ssa_var_info = ssa->var_info;
- for (i = 0; i < op_array->last_var; i++) {
- if (!op_array->function_name) {
+ if (!op_array->function_name) {
+ for (i = 0; i < op_array->last_var; i++) {
ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
- } else if (i == EX_VAR_TO_NUM(op_array->this_var)) {
- ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_OBJECT;
- ssa_var_info[i].ce = op_array->scope;
- ssa_var_info[i].is_instanceof = 1;
- } else {
- ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RCN;
+ ssa_var_info[i].has_range = 0;
+ }
+ } else {
+ for (i = 0; i < op_array->last_var; i++) {
+ if (i == EX_VAR_TO_NUM(op_array->this_var)) {
+ ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_OBJECT;
+ ssa_var_info[i].ce = op_array->scope;
+ ssa_var_info[i].is_instanceof = 1;
+ } else {
+ ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RCN;
+ }
+ ssa_var_info[i].has_range = 0;
}
- ssa_var_info[i].has_range = 0;
}
for (i = op_array->last_var; i < ssa->vars_count; i++) {
ssa_var_info[i].type = 0;
diff --git a/ext/opcache/Optimizer/zend_ssa.c b/ext/opcache/Optimizer/zend_ssa.c
index 059550b63d..16d22dd258 100644
--- a/ext/opcache/Optimizer/zend_ssa.c
+++ b/ext/opcache/Optimizer/zend_ssa.c
@@ -21,6 +21,7 @@
#include "zend_dfg.h"
#include "zend_ssa.h"
#include "zend_dump.h"
+#include "zend_inference.h"
static int needs_pi(const zend_op_array *op_array, zend_dfg *dfg, zend_ssa *ssa, int from, int to, int var) /* {{{ */
{
@@ -78,6 +79,7 @@ static void pi_range(
phi->constraint.range.underflow = underflow;
phi->constraint.range.overflow = overflow;
phi->constraint.negative = negative ? NEG_INIT : NEG_NONE;
+ phi->constraint.type_mask = (uint32_t) -1;
}
/* }}} */
@@ -94,6 +96,27 @@ static inline void pi_range_max(zend_ssa_phi *phi, int var, zend_long val) {
pi_range(phi, -1, var, ZEND_LONG_MIN, val, 1, 0, 0);
}
+static void pi_type_mask(zend_ssa_phi *phi, uint32_t type_mask) {
+ phi->constraint.type_mask = MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN;
+ phi->constraint.type_mask |= type_mask;
+ if (type_mask & MAY_BE_NULL) {
+ phi->constraint.type_mask |= MAY_BE_UNDEF;
+ }
+}
+static inline void pi_not_type_mask(zend_ssa_phi *phi, uint32_t type_mask) {
+ uint32_t relevant = MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
+ pi_type_mask(phi, ~type_mask & relevant);
+}
+static inline uint32_t mask_for_type_check(uint32_t type) {
+ if (type == _IS_BOOL) {
+ return MAY_BE_TRUE|MAY_BE_FALSE;
+ } else if (type == IS_ARRAY) {
+ return MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
+ } else {
+ return 1 << type;
+ }
+}
+
/* We can interpret $a + 5 == 0 as $a = 0 - 5, i.e. shift the adjustment to the other operand.
* This negated adjustment is what is written into the "adjustment" parameter. */
static int find_adjusted_tmp_var(const zend_op_array *op_array, uint32_t build_flags, zend_op *opline, uint32_t var_num, zend_long *adjustment)
@@ -805,6 +828,59 @@ int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t b
if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var))) {
pi_range_not_equals(pi, -1, 0);
}
+ } else if (opline->op1_type == IS_TMP_VAR && (opline-1)->opcode == ZEND_TYPE_CHECK &&
+ opline->op1.var == (opline-1)->result.var && (opline-1)->op1_type == IS_CV) {
+ int var = EX_VAR_TO_NUM((opline-1)->op1.var);
+ uint32_t type = (opline-1)->extended_value;
+ if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var))) {
+ pi_type_mask(pi, mask_for_type_check(type));
+ }
+ if (type != IS_OBJECT && type != IS_RESOURCE) {
+ /* is_object() and is_resource() may return false, even though the value is
+ * an object/resource. */
+ if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var))) {
+ pi_not_type_mask(pi, mask_for_type_check(type));
+ }
+ }
+ } else if (opline->op1_type == IS_TMP_VAR &&
+ ((opline-1)->opcode == ZEND_IS_IDENTICAL
+ || (opline-1)->opcode == ZEND_IS_NOT_IDENTICAL) &&
+ opline->op1.var == (opline-1)->result.var) {
+ int var;
+ zval *val;
+ uint32_t type_mask;
+ if ((opline-1)->op1_type == IS_CV && (opline-1)->op2_type == IS_CONST) {
+ var = EX_VAR_TO_NUM((opline-1)->op1.var);
+ val = CRT_CONSTANT((opline-1)->op2);
+ } else if ((opline-1)->op1_type == IS_CONST && (opline-1)->op2_type == IS_CV) {
+ var = EX_VAR_TO_NUM((opline-1)->op2.var);
+ val = CRT_CONSTANT((opline-1)->op1);
+ } else {
+ continue;
+ }
+
+ /* We're interested in === null/true/false comparisons here, because they eliminate
+ * a type in the false-branch. Other === VAL comparisons are unlikely to be useful. */
+ if (Z_TYPE_P(val) != IS_NULL && Z_TYPE_P(val) != IS_TRUE && Z_TYPE_P(val) != IS_FALSE) {
+ continue;
+ }
+
+ type_mask = _const_op_type(val);
+ if ((opline-1)->opcode == ZEND_IS_IDENTICAL) {
+ if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var))) {
+ pi_type_mask(pi, type_mask);
+ }
+ if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var))) {
+ pi_not_type_mask(pi, type_mask);
+ }
+ } else {
+ if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bf, var))) {
+ pi_type_mask(pi, type_mask);
+ }
+ if ((pi = add_pi(arena, op_array, &dfg, ssa, j, bt, var))) {
+ pi_not_type_mask(pi, type_mask);
+ }
+ }
}
}
diff --git a/ext/opcache/Optimizer/zend_ssa.h b/ext/opcache/Optimizer/zend_ssa.h
index 0e1bc84dbc..00d6875dfd 100644
--- a/ext/opcache/Optimizer/zend_ssa.h
+++ b/ext/opcache/Optimizer/zend_ssa.h
@@ -38,21 +38,22 @@ typedef enum _zend_ssa_negative_lat {
} zend_ssa_negative_lat;
/* Special kind of SSA Phi function used in eSSA */
-typedef struct _zend_ssa_pi_range {
+typedef struct _zend_ssa_pi_constraint {
zend_ssa_range range; /* simple range constraint */
int min_var;
int max_var;
int min_ssa_var; /* ((min_var>0) ? MIN(ssa_var) : 0) + range.min */
int max_ssa_var; /* ((man_var>0) ? MAX(ssa_var) : 0) + range.man */
zend_ssa_negative_lat negative;
-} zend_ssa_pi_range;
+ uint32_t type_mask; /* If -1 this is a range constraint */
+} zend_ssa_pi_constraint;
/* SSA Phi - ssa_var = Phi(source0, source1, ...sourceN) */
typedef struct _zend_ssa_phi zend_ssa_phi;
struct _zend_ssa_phi {
zend_ssa_phi *next; /* next Phi in the same BB */
int pi; /* if >= 0 this is actually a e-SSA Pi */
- zend_ssa_pi_range constraint; /* e-SSA Pi constraint */
+ zend_ssa_pi_constraint constraint; /* e-SSA Pi constraint */
int var; /* Original CV, VAR or TMP variable index */
int ssa_var; /* SSA variable index */
int block; /* current BB index */
diff --git a/ext/readline/config.w32 b/ext/readline/config.w32
new file mode 100644
index 0000000000..482c99cc04
--- /dev/null
+++ b/ext/readline/config.w32
@@ -0,0 +1,16 @@
+// $Id$
+// vim:ft=javascript
+
+ARG_WITH("readline", "Readline support", "yes");
+
+if (PHP_READLINE != "no") {
+ if (CHECK_LIB("edit_a.lib;edit.lib", "readline", PHP_READLINE) &&
+ CHECK_HEADER_ADD_INCLUDE("editline/readline.h", "CFLAGS_READLINE")) {
+ EXTENSION("readline", "readline.c readline_cli.c");
+ ADD_FLAG("CFLAGS_READLINE", "/D HAVE_LIBEDIT");
+ ADD_FLAG("CFLAGS_READLINE", "/D HAVE_RL_COMPLETION_MATCHES");
+ } else {
+ WARNING("readline not enabled; libraries and headers not found");
+ }
+}
+
diff --git a/ext/readline/php_readline.h b/ext/readline/php_readline.h
index 52dabdadeb..e3a0aba676 100644
--- a/ext/readline/php_readline.h
+++ b/ext/readline/php_readline.h
@@ -22,9 +22,11 @@
#define PHP_READLINE_H
#if HAVE_LIBREADLINE || HAVE_LIBEDIT
+#ifndef PHP_WIN32
#ifdef ZTS
#warning Readline module will *NEVER* be thread-safe
#endif
+#endif
extern zend_module_entry readline_module_entry;
#define phpext_readline_ptr &readline_module_entry
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index ad9b01a946..0e6f849444 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -251,7 +251,9 @@ PHP_FUNCTION(readline_info)
array_init(return_value);
add_assoc_string(return_value,"line_buffer",SAFE_STRING(rl_line_buffer));
add_assoc_long(return_value,"point",rl_point);
+#ifndef PHP_WIN32
add_assoc_long(return_value,"end",rl_end);
+#endif
#ifdef HAVE_LIBREADLINE
add_assoc_long(return_value,"mark",rl_mark);
add_assoc_long(return_value,"done",rl_done);
@@ -262,7 +264,9 @@ PHP_FUNCTION(readline_info)
#if HAVE_ERASE_EMPTY_LINE
add_assoc_long(return_value,"erase_empty_line",rl_erase_empty_line);
#endif
+#ifndef PHP_WIN32
add_assoc_string(return_value,"library_version",(char *)SAFE_STRING(rl_library_version));
+#endif
add_assoc_string(return_value,"readline_name",(char *)SAFE_STRING(rl_readline_name));
add_assoc_long(return_value,"attempted_completion_over",rl_attempted_completion_over);
} else {
@@ -276,8 +280,10 @@ PHP_FUNCTION(readline_info)
RETVAL_STRING(SAFE_STRING(oldstr));
} else if (!strcasecmp(what, "point")) {
RETVAL_LONG(rl_point);
+#ifndef PHP_WIN32
} else if (!strcasecmp(what, "end")) {
RETVAL_LONG(rl_end);
+#endif
#ifdef HAVE_LIBREADLINE
} else if (!strcasecmp(what, "mark")) {
RETVAL_LONG(rl_mark);
@@ -309,8 +315,10 @@ PHP_FUNCTION(readline_info)
}
RETVAL_LONG(oldval);
#endif
+#ifndef PHP_WIN32
} else if (!strcasecmp(what,"library_version")) {
RETVAL_STRING((char *)SAFE_STRING(rl_library_version));
+#endif
} else if (!strcasecmp(what, "readline_name")) {
oldstr = (char*)rl_readline_name;
if (value) {
diff --git a/ext/readline/readline_cli.c b/ext/readline/readline_cli.c
index 0cdf9f4ae8..6f4e47d42b 100644
--- a/ext/readline/readline_cli.c
+++ b/ext/readline/readline_cli.c
@@ -19,6 +19,10 @@
/* $Id$ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include "php.h"
#ifndef HAVE_RL_COMPLETION_MATCHES
@@ -63,7 +67,7 @@
#include "sapi/cli/cli.h"
#include "readline_cli.h"
-#ifdef COMPILE_DL_READLINE
+#if defined(COMPILE_DL_READLINE) && !defined(PHP_WIN32)
#include <dlfcn.h>
#endif
@@ -598,9 +602,15 @@ static int readline_shell_run(void) /* {{{ */
zend_execute_scripts(ZEND_REQUIRE, NULL, 1, prepend_file_p);
}
+#ifndef PHP_WIN32
history_file = tilde_expand("~/.php_history");
+#else
+ spprintf(&history_file, MAX_PATH, "%s/.php_history", getenv("USERPROFILE"));
+#endif
rl_attempted_completion_function = cli_code_completion;
+#ifndef PHP_WIN32
rl_special_prefixes = "$";
+#endif
read_history(history_file);
EG(exit_status) = 0;
@@ -686,13 +696,33 @@ static int readline_shell_run(void) /* {{{ */
php_last_char = '\0';
}
+#ifdef PHP_WIN32
+ efree(history_file);
+#else
free(history_file);
+#endif
efree(code);
zend_string_release(prompt);
return EG(exit_status);
}
/* }}} */
+#ifdef PHP_WIN32
+typedef cli_shell_callbacks_t *(__cdecl *get_cli_shell_callbacks)(void);
+#define GET_SHELL_CB(cb) \
+ do { \
+ get_cli_shell_callbacks get_callbacks; \
+ HMODULE hMod = GetModuleHandle("php.exe"); \
+ (cb) = NULL; \
+ if (strlen(sapi_module.name) >= 3 && 0 == strncmp("cli", sapi_module.name, 3)) { \
+ get_callbacks = (get_cli_shell_callbacks)GetProcAddress(hMod, "php_cli_get_shell_callbacks"); \
+ if (get_callbacks) { \
+ (cb) = get_callbacks(); \
+ } \
+ } \
+ } while(0)
+
+#else
/*
#ifdef COMPILE_DL_READLINE
This dlsym() is always used as even the CGI SAPI is linked against "CLI"-only
@@ -711,6 +741,7 @@ this extension sharedto offer compatibility.
/*#else
#define GET_SHELL_CB(cb) (cb) = php_cli_get_shell_callbacks()
#endif*/
+#endif
PHP_MINIT_FUNCTION(cli_readline)
{
@@ -755,7 +786,11 @@ PHP_MINFO_FUNCTION(cli_readline)
{
php_info_print_table_start();
php_info_print_table_header(2, "Readline Support", "enabled");
+#ifdef PHP_WIN32
+ php_info_print_table_row(2, "Readline library", "WinEditLine");
+#else
php_info_print_table_row(2, "Readline library", (rl_library_version ? rl_library_version : "Unknown"));
+#endif
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
diff --git a/ext/readline/tests/libedit_info_001-win32.phpt b/ext/readline/tests/libedit_info_001-win32.phpt
new file mode 100644
index 0000000000..5d43921c60
--- /dev/null
+++ b/ext/readline/tests/libedit_info_001-win32.phpt
@@ -0,0 +1,42 @@
+--TEST--
+readline_info(): Basic test
+--SKIPIF--
+<?php if (!extension_loaded("readline")) die("skip");
+if (READLINE_LIB != "libedit") die("skip libedit only");
+if(substr(PHP_OS, 0, 3) != 'WIN' ) {
+ die('skip windows only test');
+}
+?>
+--FILE--
+<?php
+
+var_dump(readline_info());
+var_dump(readline_info(1));
+var_dump(readline_info(1,1));
+var_dump(readline_info('line_buffer'));
+var_dump(readline_info('readline_name'));
+var_dump(readline_info('readline_name', 1));
+var_dump(readline_info('readline_name'));
+var_dump(readline_info('attempted_completion_over',1));
+var_dump(readline_info('attempted_completion_over'));
+
+?>
+--EXPECTF--
+array(4) {
+ ["line_buffer"]=>
+ string(0) ""
+ ["point"]=>
+ int(0)
+ ["readline_name"]=>
+ string(0) ""
+ ["attempted_completion_over"]=>
+ int(0)
+}
+NULL
+NULL
+string(0) ""
+string(0) ""
+string(0) ""
+string(1) "1"
+int(0)
+int(1)
diff --git a/ext/readline/tests/libedit_info_001.phpt b/ext/readline/tests/libedit_info_001.phpt
index 1d79f4ad0c..33dc144add 100644
--- a/ext/readline/tests/libedit_info_001.phpt
+++ b/ext/readline/tests/libedit_info_001.phpt
@@ -3,6 +3,9 @@ readline_info(): Basic test
--SKIPIF--
<?php if (!extension_loaded("readline")) die("skip");
if (READLINE_LIB != "libedit") die("skip libedit only");
+if(substr(PHP_OS, 0, 3) == 'WIN' ) {
+ die('skip not for windows');
+}
?>
--FILE--
<?php
diff --git a/ext/readline/tests/libedit_write_history_001-win32.phpt b/ext/readline/tests/libedit_write_history_001-win32.phpt
new file mode 100644
index 0000000000..28af4cbfdd
--- /dev/null
+++ b/ext/readline/tests/libedit_write_history_001-win32.phpt
@@ -0,0 +1,29 @@
+--TEST--
+readline_write_history(): Basic test
+--SKIPIF--
+<?php if (!extension_loaded("readline") || !function_exists('readline_add_history')) die("skip");
+if (READLINE_LIB != "libedit") die("skip libedit only");
+if(substr(PHP_OS, 0, 3) != 'WIN' ) {
+ die('skip windows only test');
+}
+?>
+--FILE--
+<?php
+
+$name = tempnam(sys_get_temp_dir(), 'readline.tmp');
+
+readline_add_history('foo');
+readline_add_history('');
+readline_add_history(1);
+readline_add_history(NULL);
+readline_write_history($name);
+
+var_dump(file_get_contents($name));
+
+unlink($name);
+
+?>
+--EXPECT--
+string(6) "foo
+1
+"
diff --git a/ext/readline/tests/libedit_write_history_001.phpt b/ext/readline/tests/libedit_write_history_001.phpt
index e9b6dbee8d..14c3282e6d 100644
--- a/ext/readline/tests/libedit_write_history_001.phpt
+++ b/ext/readline/tests/libedit_write_history_001.phpt
@@ -3,6 +3,9 @@ readline_write_history(): Basic test
--SKIPIF--
<?php if (!extension_loaded("readline") || !function_exists('readline_add_history')) die("skip");
if (READLINE_LIB != "libedit") die("skip libedit only");
+if(substr(PHP_OS, 0, 3) == 'WIN' ) {
+ die('skip not for windows');
+}
?>
--FILE--
<?php
diff --git a/ext/session/mod_user.c b/ext/session/mod_user.c
index e6f162855a..c7c09ff781 100644
--- a/ext/session/mod_user.c
+++ b/ext/session/mod_user.c
@@ -85,7 +85,16 @@ PS_OPEN_FUNC(user)
ZVAL_STRING(&args[0], (char*)save_path);
ZVAL_STRING(&args[1], (char*)session_name);
- ps_call_handler(&PSF(open), 2, args, &retval);
+ zend_try {
+ ps_call_handler(&PSF(open), 2, args, &retval);
+ } zend_catch {
+ PS(session_status) = php_session_none;
+ if (!Z_ISUNDEF(retval)) {
+ zval_ptr_dtor(&retval);
+ }
+ zend_bailout();
+ } zend_end_try();
+
PS(mod_user_implemented) = 1;
FINISH;
diff --git a/ext/session/mod_user_class.c b/ext/session/mod_user_class.c
index 59b44f5f6f..a774d4bf9c 100644
--- a/ext/session/mod_user_class.c
+++ b/ext/session/mod_user_class.c
@@ -22,6 +22,10 @@
#include "php_session.h"
#define PS_SANITY_CHECK \
+ if (PS(session_status) != php_session_active) { \
+ php_error_docref(NULL, E_WARNING, "Session is not active"); \
+ RETURN_FALSE; \
+ } \
if (PS(default_mod) == NULL) { \
php_error_docref(NULL, E_CORE_ERROR, "Cannot call default session handler"); \
RETURN_FALSE; \
@@ -40,6 +44,7 @@ PHP_METHOD(SessionHandler, open)
{
char *save_path = NULL, *session_name = NULL;
size_t save_path_len, session_name_len;
+ int ret;
PS_SANITY_CHECK;
@@ -48,7 +53,15 @@ PHP_METHOD(SessionHandler, open)
}
PS(mod_user_is_open) = 1;
- RETVAL_BOOL(SUCCESS == PS(default_mod)->s_open(&PS(mod_data), save_path, session_name));
+
+ zend_try {
+ ret = PS(default_mod)->s_open(&PS(mod_data), save_path, session_name);
+ } zend_catch {
+ PS(session_status) = php_session_none;
+ zend_bailout();
+ } zend_end_try();
+
+ RETVAL_BOOL(SUCCESS == ret);
}
/* }}} */
@@ -56,6 +69,8 @@ PHP_METHOD(SessionHandler, open)
Wraps the old close handler */
PHP_METHOD(SessionHandler, close)
{
+ int ret;
+
PS_SANITY_CHECK_IS_OPEN;
// don't return on failure, since not closing the default handler
@@ -63,7 +78,15 @@ PHP_METHOD(SessionHandler, close)
zend_parse_parameters_none();
PS(mod_user_is_open) = 0;
- RETVAL_BOOL(SUCCESS == PS(default_mod)->s_close(&PS(mod_data)));
+
+ zend_try {
+ ret = PS(default_mod)->s_close(&PS(mod_data));
+ } zend_catch {
+ PS(session_status) = php_session_none;
+ zend_bailout();
+ } zend_end_try();
+
+ RETVAL_BOOL(SUCCESS == ret);
}
/* }}} */
diff --git a/ext/session/session.c b/ext/session/session.c
index f5a399b75f..22a7ec125d 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -103,6 +103,7 @@ static void php_session_abort(void);
static inline void php_rinit_session_globals(void) /* {{{ */
{
/* Do NOT init PS(mod_user_names) here! */
+ /* TODO: These could be moved to MINIT and removed. These should be initialized by php_rshutdown_session_globals() always when execution is finished. */
PS(id) = NULL;
PS(session_status) = php_session_none;
PS(mod_data) = NULL;
@@ -130,10 +131,15 @@ static inline void php_rshutdown_session_globals(void) /* {{{ */
zend_string_release(PS(id));
PS(id) = NULL;
}
+
if (PS(session_vars)) {
zend_string_release(PS(session_vars));
PS(session_vars) = NULL;
}
+
+ /* User save handlers may end up directly here by misuse, bugs in user script, etc. */
+ /* Set session status to prevent error while restoring save handler INI value. */
+ PS(session_status) = php_session_none;
}
/* }}} */
@@ -522,7 +528,10 @@ static void php_session_initialize(void) /* {{{ */
}
/* If there is no ID, use session module to create one */
- if (!PS(id)) {
+ if (!PS(id) || !ZSTR_VAL(PS(id))[0]) {
+ if (PS(id)) {
+ zend_string_release(PS(id));
+ }
PS(id) = PS(mod)->s_create_sid(&PS(mod_data));
if (!PS(id)) {
php_session_abort();
@@ -602,11 +611,16 @@ static void php_session_save_current_state(int write) /* {{{ */
}
if ((ret == FAILURE) && !EG(exception)) {
- php_error_docref(NULL, E_WARNING, "Failed to write session data (%s). Please "
- "verify that the current setting of session.save_path "
- "is correct (%s)",
- PS(mod)->s_name,
- PS(save_path));
+ if (!PS(mod_user_implemented)) {
+ php_error_docref(NULL, E_WARNING, "Failed to write session data (%s). Please "
+ "verify that the current setting of session.save_path "
+ "is correct (%s)",
+ PS(mod)->s_name,
+ PS(save_path));
+ } else {
+ php_error_docref(NULL, E_WARNING, "Failed to write session data using user "
+ "defined save handler. (session.save_path: %s)", PS(save_path));
+ }
}
}
}
@@ -1107,7 +1121,7 @@ static ps_serializer ps_serializers[MAX_SERIALIZERS + 1] = {
PHPAPI int php_session_register_serializer(const char *name, zend_string *(*encode)(PS_SERIALIZER_ENCODE_ARGS), int (*decode)(PS_SERIALIZER_DECODE_ARGS)) /* {{{ */
{
- int ret = -1;
+ int ret = FAILURE;
int i;
for (i = 0; i < MAX_SERIALIZERS; i++) {
@@ -1116,7 +1130,7 @@ PHPAPI int php_session_register_serializer(const char *name, zend_string *(*enco
ps_serializers[i].encode = encode;
ps_serializers[i].decode = decode;
ps_serializers[i + 1].name = NULL;
- ret = 0;
+ ret = SUCCESS;
break;
}
}
@@ -1138,13 +1152,13 @@ static ps_module *ps_modules[MAX_MODULES + 1] = {
PHPAPI int php_session_register_module(ps_module *ptr) /* {{{ */
{
- int ret = -1;
+ int ret = FAILURE;
int i;
for (i = 0; i < MAX_MODULES; i++) {
if (!ps_modules[i]) {
ps_modules[i] = ptr;
- ret = 0;
+ ret = SUCCESS;
break;
}
}
@@ -1659,8 +1673,8 @@ PHPAPI void php_session_start(void) /* {{{ */
static void php_session_flush(int write) /* {{{ */
{
if (PS(session_status) == php_session_active) {
- PS(session_status) = php_session_none;
php_session_save_current_state(write);
+ PS(session_status) = php_session_none;
}
}
/* }}} */
@@ -1668,10 +1682,10 @@ static void php_session_flush(int write) /* {{{ */
static void php_session_abort(void) /* {{{ */
{
if (PS(session_status) == php_session_active) {
- PS(session_status) = php_session_none;
if (PS(mod_data) || PS(mod_user_implemented)) {
PS(mod)->s_close(&PS(mod_data));
}
+ PS(session_status) = php_session_none;
}
}
/* }}} */
@@ -2046,13 +2060,13 @@ static PHP_FUNCTION(session_regenerate_id)
return;
}
- if (SG(headers_sent) && PS(use_cookies)) {
- php_error_docref(NULL, E_WARNING, "Cannot regenerate session id - headers already sent");
+ if (PS(session_status) != php_session_active) {
+ php_error_docref(NULL, E_WARNING, "Cannot regenerate session id - session is not active");
RETURN_FALSE;
}
- if (PS(session_status) != php_session_active) {
- php_error_docref(NULL, E_WARNING, "Cannot regenerate session id - session is not active");
+ if (SG(headers_sent) && PS(use_cookies)) {
+ php_error_docref(NULL, E_WARNING, "Cannot regenerate session id - headers already sent");
RETURN_FALSE;
}
@@ -2104,6 +2118,7 @@ static PHP_FUNCTION(session_regenerate_id)
zend_string_release(PS(id));
PS(id) = PS(mod)->s_create_sid(&PS(mod_data));
if (!PS(id)) {
+ PS(mod)->s_close(&PS(mod_data));
PS(session_status) = php_session_none;
php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to create session ID by collision: %s (path: %s)", PS(mod)->s_name, PS(save_path));
RETURN_FALSE;
@@ -2111,6 +2126,7 @@ static PHP_FUNCTION(session_regenerate_id)
}
/* Read is required to make new session data at this point. */
if (PS(mod)->s_read(&PS(mod_data), PS(id), &data, PS(gc_maxlifetime)) == FAILURE) {
+ PS(mod)->s_close(&PS(mod_data));
PS(session_status) = php_session_none;
php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to create(read) session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path));
RETURN_FALSE;
@@ -2282,11 +2298,6 @@ static PHP_FUNCTION(session_start)
RETURN_FALSE;
}
- if (PS(id) && !(ZSTR_LEN(PS(id)))) {
- php_error_docref(NULL, E_WARNING, "Cannot start session with empty session ID");
- RETURN_FALSE;
- }
-
/* set options */
if (options) {
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(options), num_idx, str_idx, value) {
diff --git a/ext/session/tests/bug55688.phpt b/ext/session/tests/bug55688.phpt
index 8db48384af..b073dc3c5c 100644
--- a/ext/session/tests/bug55688.phpt
+++ b/ext/session/tests/bug55688.phpt
@@ -12,4 +12,4 @@ $x = new SessionHandler;
$x->gc(1);
?>
--EXPECTF--
-Warning: SessionHandler::gc(): Parent session handler is not open in %s on line %d
+Warning: SessionHandler::gc(): Session is not active in %s on line %d
diff --git a/ext/session/tests/bug60634.phpt b/ext/session/tests/bug60634.phpt
index 86dcb11526..b2f5076287 100644
--- a/ext/session/tests/bug60634.phpt
+++ b/ext/session/tests/bug60634.phpt
@@ -39,8 +39,17 @@ session_start();
session_write_close();
echo "um, hi\n";
+/*
+FIXME: Since session module try to write/close session data in
+RSHUTDOWN, write() is executed twices. This is caused by undefined
+function error and zend_bailout(). Current session module codes
+depends on this behavior. These codes should be modified to remove
+multiple write().
+*/
+
?>
--EXPECTF--
write: goodbye cruel world
+write: goodbye cruel world
close: goodbye cruel world
diff --git a/ext/session/tests/bug60634_error_1.phpt b/ext/session/tests/bug60634_error_1.phpt
index d0733f5a5a..fa76ff522a 100644
--- a/ext/session/tests/bug60634_error_1.phpt
+++ b/ext/session/tests/bug60634_error_1.phpt
@@ -41,6 +41,11 @@ session_start();
session_write_close();
echo "um, hi\n";
+/*
+FIXME: Something wrong. It should try to close after error, otherwise session
+may keep "open" state.
+*/
+
?>
--EXPECTF--
write: goodbye cruel world
@@ -51,3 +56,4 @@ Stack trace:
#1 %s(%d): session_write_close()
#2 {main}
thrown in %s on line %d
+
diff --git a/ext/session/tests/bug67972.phpt b/ext/session/tests/bug67972.phpt
index 63ed3a95b8..92c3044ac5 100644
--- a/ext/session/tests/bug67972.phpt
+++ b/ext/session/tests/bug67972.phpt
@@ -7,4 +7,5 @@ Bug #67972: SessionHandler Invalid memory read create_sid()
(new SessionHandler)->create_sid();
--EXPECTF--
-Fatal error: SessionHandler::create_sid(): Cannot call default session handler in %s on line %d
+Warning: SessionHandler::create_sid(): Session is not active in %s on line %d
+
diff --git a/ext/session/tests/bug68063.phpt b/ext/session/tests/bug68063.phpt
index d3da470d06..ec3a70d156 100644
--- a/ext/session/tests/bug68063.phpt
+++ b/ext/session/tests/bug68063.phpt
@@ -3,18 +3,22 @@ Bug #68063 (Empty session IDs do still start sessions)
--SKIPIF--
<?php include('skipif.inc'); ?>
--INI--
+session.use_strict_mode=0
+session.hash_function=1
+session.hash_bits_per_character=4
--FILE--
<?php
+// Empty session ID may happen by browser bugs
+
// Could also be set with a cookie like "PHPSESSID=; path=/"
session_id('');
-// Will still start the session and return true
+// Start the session with empty string should result in new session ID
var_dump(session_start());
-// Returns an empty string
+// Returns newly created session ID
var_dump(session_id());
?>
--EXPECTF--
-Warning: session_start(): Cannot start session with empty session ID in %s on line %d
-bool(false)
-string(0) ""
+bool(true)
+string(40) "%s"
diff --git a/ext/session/tests/bug69111.phpt b/ext/session/tests/bug69111.phpt
new file mode 100644
index 0000000000..f5def0ed35
--- /dev/null
+++ b/ext/session/tests/bug69111.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #69111 (Crash in SessionHandler::read())
+--INI--
+session.save_path=
+session.save_handler=files
+session.name=PHPSESSID
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--FILE--
+<?php
+$sh = new SessionHandler;
+session_set_save_handler($sh);
+
+$savePath = ini_get('session.save_path');
+$sessionName = ini_get('session.name');
+
+// session_start(); // Uncommenting this makes it not crash when reading the session (see below), but it will not return any data.
+
+$sh->open($savePath, $sessionName);
+$sh->write("foo", "bar");
+$sh->read($id);
+$sh->gc(1245);
+$sh->close();
+?>
+--EXPECTF--
+Warning: SessionHandler::open(): Session is not active in %s on line 10
+
+Warning: SessionHandler::write(): Session is not active in %s on line 11
+
+Notice: Undefined variable: id in %s on line 12
+
+Warning: SessionHandler::read(): Session is not active in %s on line 12
+
+Warning: SessionHandler::gc(): Session is not active in %s on line 13
+
+Warning: SessionHandler::close(): Session is not active in %s on line 14 \ No newline at end of file
diff --git a/ext/session/tests/bug70133.phpt b/ext/session/tests/bug70133.phpt
new file mode 100644
index 0000000000..3e019e483b
--- /dev/null
+++ b/ext/session/tests/bug70133.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Bug #70133 (Extended SessionHandler::read is ignoring $session_id when calling parent)
+--SKIPIF--
+<?php include('skipif.inc'); ?>
+--INI--
+session.save_handler=files
+session.save_path=
+session.use_strict_mode=0
+--FILE--
+<?php
+
+class CustomReadHandler extends \SessionHandler {
+
+ public function read($session_id) {
+ return parent::read('mycustomsession');
+ }
+}
+
+ob_start();
+
+session_set_save_handler(new CustomReadHandler(), true);
+
+session_id('mycustomsession');
+session_start();
+$_SESSION['foo'] = 'hoge';
+var_dump(session_id());
+session_commit();
+
+session_id('otherid');
+session_start();
+var_dump($_SESSION);
+var_dump(session_id());
+
+?>
+--EXPECT--
+string(15) "mycustomsession"
+array(1) {
+ ["foo"]=>
+ string(4) "hoge"
+}
+string(7) "otherid"
diff --git a/ext/session/tests/sessionhandler_open_001.phpt b/ext/session/tests/sessionhandler_open_001.phpt
index 6ade9e00a5..e6e913a6a5 100644
--- a/ext/session/tests/sessionhandler_open_001.phpt
+++ b/ext/session/tests/sessionhandler_open_001.phpt
@@ -16,4 +16,11 @@ print "Done!\n";
?>
--EXPECTF--
+Warning: SessionHandler::open(): Session is not active in %s on line 5
+
+Warning: SessionHandler::open(): Session is not active in %s on line 6
+
+Warning: SessionHandler::open(): Session is not active in %s on line 7
+
+Warning: SessionHandler::open(): Session is not active in %s on line 8
Done!
diff --git a/ext/soap/soap.c b/ext/soap/soap.c
index 49fc72d68f..ee41ff908f 100644
--- a/ext/soap/soap.c
+++ b/ext/soap/soap.c
@@ -2135,7 +2135,7 @@ static void soap_error_handler(int error_num, const char *error_filename, const
_old_http_response_code = SG(sapi_headers).http_response_code;
_old_http_status_line = SG(sapi_headers).http_status_line;
- if (!SOAP_GLOBAL(use_soap_error_handler) || !EG(objects_store).object_buckets) {
+ if (!PG(modules_activated) || !SOAP_GLOBAL(use_soap_error_handler) || !EG(objects_store).object_buckets) {
call_old_error_handler(error_num, error_filename, error_lineno, format, args);
return;
}
diff --git a/ext/sockets/tests/socket_clear_error-win32.phpt b/ext/sockets/tests/socket_clear_error-win32.phpt
new file mode 100644
index 0000000000..3a0b1ea162
--- /dev/null
+++ b/ext/sockets/tests/socket_clear_error-win32.phpt
@@ -0,0 +1,32 @@
+--TEST--
+void socket_clear_error ([ resource $socket ] ) ;
+--CREDITS--
+marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao paulo - br
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('SKIP sockets extension not available.');
+}
+if(substr(PHP_OS, 0, 3) != 'WIN' ) {
+ die('skip windows only test');
+}
+?>
+--FILE--
+<?php
+$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
+$socketConn = socket_connect($socket, "127.0.0.1", 21248);
+var_dump(socket_last_error($socket));
+socket_clear_error($socket);
+var_dump(socket_last_error($socket));
+?>
+--CLEAN--
+<?php
+socket_close($socket);
+unset($socket);
+unset($socketConn);
+?>
+--EXPECTF--
+Warning: socket_connect(): unable to connect [%d]: No connection could be made because the target machine actively refused it.
+ in %s on line %d
+int(%d)
+int(%d)
diff --git a/ext/sockets/tests/socket_clear_error.phpt b/ext/sockets/tests/socket_clear_error.phpt
index af9acaa9bf..273f7a0ca8 100644
--- a/ext/sockets/tests/socket_clear_error.phpt
+++ b/ext/sockets/tests/socket_clear_error.phpt
@@ -7,6 +7,9 @@ marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao p
if (!extension_loaded('sockets')) {
die('SKIP sockets extension not available.');
}
+if(substr(PHP_OS, 0, 3) == 'WIN' ) {
+ die('skip windows only test');
+}
?>
--FILE--
<?php
diff --git a/ext/sockets/tests/socket_send.phpt b/ext/sockets/tests/socket_send.phpt
index 1411868c4b..ceeb397979 100644
--- a/ext/sockets/tests/socket_send.phpt
+++ b/ext/sockets/tests/socket_send.phpt
@@ -7,6 +7,9 @@ marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao p
if (!extension_loaded('sockets')) {
die('SKIP sockets extension not available.');
}
+if(substr(PHP_OS, 0, 3) == 'WIN' ) {
+ die('skip not for windows');
+}
?>
--FILE--
<?php
diff --git a/ext/sockets/tests/socket_send_win32.phpt b/ext/sockets/tests/socket_send_win32.phpt
new file mode 100644
index 0000000000..04a985c781
--- /dev/null
+++ b/ext/sockets/tests/socket_send_win32.phpt
@@ -0,0 +1,43 @@
+--TEST--
+int socket_send ( resource $socket , string $buf , int $len , int $flags );
+--CREDITS--
+marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao paulo - br
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('SKIP sockets extension not available.');
+}
+if(substr(PHP_OS, 0, 3) != 'WIN' ) {
+ die('skip windows only test');
+}
+?>
+--FILE--
+<?php
+$port = 80;
+$host = "yahoo.com";
+$stringSocket = "send_socket_to_connected_socket";
+$stringSocketLenght = strlen($stringSocket);
+
+$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
+$socketConn = socket_connect($socket, $host, $port);
+
+if(socket_send($socket, $stringSocket, $stringSocketLenght, MSG_OOB)===$stringSocketLenght){
+ print("okey\n");
+}
+
+if(socket_send($socket, $stringSocket, $stringSocketLenght, MSG_DONTROUTE)===$stringSocketLenght){
+ print("okey\n");
+}
+?>
+<?php
+socket_close($socket);
+unset($port);
+unset($host);
+unset($stringSocket);
+unset($stringSocketLenght);
+unset($socket);
+unset($socketConn);
+?>
+--EXPECTF--
+okey
+okey
diff --git a/ext/sockets/tests/socket_shutdown-win32.phpt b/ext/sockets/tests/socket_shutdown-win32.phpt
new file mode 100644
index 0000000000..6280e61044
--- /dev/null
+++ b/ext/sockets/tests/socket_shutdown-win32.phpt
@@ -0,0 +1,59 @@
+--TEST--
+bool socket_shutdown ( resource $socket [, int $how = 2 ] ) ;
+--CREDITS--
+marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao paulo - br
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets')) {
+ die('SKIP sockets extension not available.');
+}
+if(substr(PHP_OS, 0, 3) != 'WIN' ) {
+ die('skip windows only test');
+}
+?>
+--FILE--
+<?php
+$host = "yahoo.com";
+$port = 80;
+
+$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
+$socketConn = socket_connect($socket, $host, $port);
+var_dump(socket_shutdown($socket,0));
+socket_close($socket);
+
+$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
+$socketConn = socket_connect($socket, $host, $port);
+var_dump(socket_shutdown($socket,1));
+socket_close($socket);
+
+$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
+$socketConn = socket_connect($socket, $host, $port);
+var_dump(socket_shutdown($socket,2));
+socket_close($socket);
+
+$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
+var_dump(socket_shutdown($socket,0));
+
+$socketConn = socket_connect($socket, $host, $port);
+var_dump(socket_shutdown($socket,-1));
+socket_close($socket);
+?>
+--CLEAN--
+<?php
+unset($host);
+unset($port);
+unset($socket);
+unset($socketConn);
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+bool(true)
+
+Warning: socket_shutdown(): unable to shutdown socket [%d]: A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.
+ in %s on line %d
+bool(false)
+
+Warning: socket_shutdown(): unable to shutdown socket [%d]: An invalid argument was supplied.
+ in %s on line %d
+bool(false)
diff --git a/ext/sockets/tests/socket_shutdown.phpt b/ext/sockets/tests/socket_shutdown.phpt
index 09f5ac73fc..77cbc8f32c 100644
--- a/ext/sockets/tests/socket_shutdown.phpt
+++ b/ext/sockets/tests/socket_shutdown.phpt
@@ -7,6 +7,9 @@ marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao p
if (!extension_loaded('sockets')) {
die('SKIP sockets extension not available.');
}
+if(substr(PHP_OS, 0, 3) == 'WIN' ) {
+ die('skip not for windows');
+}
?>
--FILE--
<?php
diff --git a/ext/standard/math.c b/ext/standard/math.c
index 7ea8dc1199..ebfee8ead8 100644
--- a/ext/standard/math.c
+++ b/ext/standard/math.c
@@ -146,6 +146,7 @@ PHPAPI double _php_math_round(double value, int places, int mode) {
return value;
}
+ places = places < INT_MIN+1 ? INT_MIN+1 : places;
precision_places = 14 - php_intlog10abs(value);
f1 = php_intpow10(abs(places));
@@ -154,8 +155,10 @@ PHPAPI double _php_math_round(double value, int places, int mode) {
the requested places BUT is small enough to make sure a non-zero value
is returned, pre-round the result to the precision */
if (precision_places > places && precision_places - places < 15) {
- f2 = php_intpow10(abs(precision_places));
- if (precision_places >= 0) {
+ int64_t use_precision = precision_places < INT_MIN+1 ? INT_MIN+1 : precision_places;
+
+ f2 = php_intpow10(abs((int)use_precision));
+ if (use_precision >= 0) {
tmp_value = value * f2;
} else {
tmp_value = value / f2;
@@ -163,8 +166,11 @@ PHPAPI double _php_math_round(double value, int places, int mode) {
/* preround the result (tmp_value will always be something * 1e14,
thus never larger than 1e15 here) */
tmp_value = php_round_helper(tmp_value, mode);
+
+ use_precision = places - precision_places;
+ use_precision = use_precision < INT_MIN+1 ? INT_MIN+1 : use_precision;
/* now correctly move the decimal point */
- f2 = php_intpow10(abs(places - precision_places));
+ f2 = php_intpow10(abs((int)use_precision));
/* because places < precision_places */
tmp_value = tmp_value / f2;
} else {
diff --git a/ext/standard/tests/streams/stream_socket_enable_crypto-win32.phpt b/ext/standard/tests/streams/stream_socket_enable_crypto-win32.phpt
new file mode 100644
index 0000000000..2f78f4a4b5
--- /dev/null
+++ b/ext/standard/tests/streams/stream_socket_enable_crypto-win32.phpt
@@ -0,0 +1,69 @@
+--TEST--
+mixed stream_socket_enable_crypto(resource $stream , bool $enable [, int $crypto_type [, resource $session_stream ]] ) ;
+--CREDITS--
+marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao paulo - br
+--SKIPIF--
+<?php
+if (phpversion() < "5.3.0") { die('SKIP php version so lower.'); }
+if (!extension_loaded('openssl')) { die('ext/openssl required'); }
+if(substr(PHP_OS, 0, 3) != 'WIN' ) {
+ die('skip windows only test');
+}
+?>
+--FILE--
+<?php
+$serverUri = "tcp://127.0.0.1:31854";
+$sock = stream_socket_server($serverUri, $errno, $errstr);
+
+if (is_resource($sock)) {
+ var_dump(stream_socket_enable_crypto($sock, false));
+ var_dump(stream_socket_enable_crypto($sock, true));
+ var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv2_CLIENT));
+ var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv3_CLIENT));
+ var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT));
+ var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_CLIENT));
+ var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv2_SERVER));
+ var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv3_SERVER));
+ var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv23_SERVER));
+ var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_SERVER));
+} else {
+ die("Test stream_socket_enable_crypto has failed; Unable to connect: {$errstr} ({$errno})");
+}
+?>
+--CLEAN--
+<?php
+unset($serverUri);
+unset($sock);
+unset($errno);
+unset($errstr);
+?>
+--EXPECTF--
+bool(false)
+
+Warning: stream_socket_enable_crypto(): When enabling encryption you must specify the crypto type in %s on line %d
+bool(false)
+
+Warning: stream_socket_enable_crypto(): SSLv2 unavailable in the OpenSSL library against which PHP is linked in %s on line %d
+bool(false)
+
+Warning: stream_socket_enable_crypto(): SSL: A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.
+ in %s on line %d
+bool(false)
+
+Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d
+bool(false)
+
+Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d
+bool(false)
+
+Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d
+bool(false)
+
+Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d
+bool(false)
+
+Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d
+bool(false)
+
+Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d
+bool(false)
diff --git a/ext/standard/tests/streams/stream_socket_enable_crypto.phpt b/ext/standard/tests/streams/stream_socket_enable_crypto.phpt
index 47d6c62893..e316096525 100644
--- a/ext/standard/tests/streams/stream_socket_enable_crypto.phpt
+++ b/ext/standard/tests/streams/stream_socket_enable_crypto.phpt
@@ -6,6 +6,9 @@ marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao p
<?php
if (phpversion() < "5.3.0") { die('SKIP php version so lower.'); }
if (!extension_loaded('openssl')) { die('ext/openssl required'); }
+if(substr(PHP_OS, 0, 3) == 'WIN' ) {
+ die('skip not for windows');
+}
?>
--FILE--
<?php
diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
index d9d6e76a8d..4e092cb0ea 100644
--- a/sapi/cgi/cgi_main.c
+++ b/sapi/cgi/cgi_main.c
@@ -35,6 +35,7 @@
#ifdef PHP_WIN32
# include "win32/time.h"
# include "win32/signal.h"
+# include "win32/winutil.h"
# include <process.h>
#endif
@@ -224,8 +225,10 @@ static php_cgi_globals_struct php_cgi_globals;
#ifdef PHP_WIN32
#define WIN32_MAX_SPAWN_CHILDREN 64
-HANDLE win32_kid_cgi_ps[WIN32_MAX_SPAWN_CHILDREN];
-int win32_kids;
+HANDLE kid_cgi_ps[WIN32_MAX_SPAWN_CHILDREN];
+int kids;
+HANDLE job = NULL;
+JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info = { 0 };
#endif
#ifndef HAVE_ATTRIBUTE_WEAK
@@ -1436,16 +1439,20 @@ void fastcgi_cleanup(int signal)
#else
BOOL fastcgi_cleanup(DWORD sig)
{
- int i = win32_kids;
+ int i = kids;
while (0 < i--) {
- if (NULL == win32_kid_cgi_ps[i]) {
+ if (NULL == kid_cgi_ps[i]) {
continue;
}
- TerminateProcess(win32_kid_cgi_ps[i], 0);
- CloseHandle(win32_kid_cgi_ps[i]);
- win32_kid_cgi_ps[i] = NULL;
+ TerminateProcess(kid_cgi_ps[i], 0);
+ CloseHandle(kid_cgi_ps[i]);
+ kid_cgi_ps[i] = NULL;
+ }
+
+ if (job) {
+ CloseHandle(job);
}
parent = 0;
@@ -2109,35 +2116,54 @@ consult the installation file that came with this distribution, or visit \n\
char my_name[MAX_PATH] = {0};
int i;
- ZeroMemory(&win32_kid_cgi_ps, sizeof(win32_kid_cgi_ps));
- win32_kids = children < WIN32_MAX_SPAWN_CHILDREN ? children : WIN32_MAX_SPAWN_CHILDREN;
+ ZeroMemory(&kid_cgi_ps, sizeof(kid_cgi_ps));
+ kids = children < WIN32_MAX_SPAWN_CHILDREN ? children : WIN32_MAX_SPAWN_CHILDREN;
SetConsoleCtrlHandler(fastcgi_cleanup, TRUE);
- SetEnvironmentVariable("PHP_FCGI_CHILDREN", NULL); /* kids will inherit the env, don't let them spawn */
+ /* kids will inherit the env, don't let them spawn */
+ SetEnvironmentVariable("PHP_FCGI_CHILDREN", NULL);
GetModuleFileName(NULL, my_name, MAX_PATH);
cmd_line = my_name;
+ job = CreateJobObject(NULL, NULL);
+ if (!job) {
+ DWORD err = GetLastError();
+ char *err_text = php_win32_error_to_msg(err);
+
+ fprintf(stderr, "unable to create job object: [0x%08lx]: %s\n", err, err_text);
+
+ goto parent_out;
+ }
+
+ job_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+ if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &job_info, sizeof(job_info))) {
+ DWORD err = GetLastError();
+ char *err_text = php_win32_error_to_msg(err);
+
+ fprintf(stderr, "unable to configure job object: [0x%08lx]: %s\n", err, err_text);
+ }
+
while (parent) {
- i = win32_kids;
+ i = kids;
while (0 < i--) {
DWORD status;
- if (NULL != win32_kid_cgi_ps[i]) {
- if(!GetExitCodeProcess(win32_kid_cgi_ps[i], &status) || status != STILL_ACTIVE) {
- CloseHandle(win32_kid_cgi_ps[i]);
- win32_kid_cgi_ps[i] = NULL;
+ if (NULL != kid_cgi_ps[i]) {
+ if(!GetExitCodeProcess(kid_cgi_ps[i], &status) || status != STILL_ACTIVE) {
+ CloseHandle(kid_cgi_ps[i]);
+ kid_cgi_ps[i] = NULL;
}
}
}
- i = win32_kids;
+ i = kids;
while (0 < i--) {
PROCESS_INFORMATION pi;
STARTUPINFO si;
- if (NULL != win32_kid_cgi_ps[i]) {
+ if (NULL != kid_cgi_ps[i]) {
continue;
}
@@ -2151,31 +2177,30 @@ consult the installation file that came with this distribution, or visit \n\
si.hStdError = INVALID_HANDLE_VALUE;
if (CreateProcess(NULL, cmd_line, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
- win32_kid_cgi_ps[i] = pi.hProcess;
+ kid_cgi_ps[i] = pi.hProcess;
+ if (!AssignProcessToJobObject(job, pi.hProcess)) {
+ DWORD err = GetLastError();
+ char *err_text = php_win32_error_to_msg(err);
+
+ fprintf(stderr, "unable to assign child process to job object: [0x%08lx]: %s\n", err, err_text);
+ }
CloseHandle(pi.hThread);
} else {
DWORD err = GetLastError();
- char *err_text;
-
- win32_kid_cgi_ps[i] = NULL;
-
- (void)FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
- NULL,
- err,
- LANG_NEUTRAL,
- (LPTSTR)&err_text,
- 0,
- NULL);
-
+ char *err_text = php_win32_error_to_msg(err);
+
+ kid_cgi_ps[i] = NULL;
+
fprintf(stderr, "unable to spawn: [0x%08lx]: %s\n", err, err_text);
}
}
- WaitForMultipleObjects(win32_kids, win32_kid_cgi_ps, FALSE, INFINITE);
+ WaitForMultipleObjects(kids, kid_cgi_ps, FALSE, INFINITE);
}
snprintf(kid_buf, 16, "%d", children);
- SetEnvironmentVariable("PHP_FCGI_CHILDREN", kid_buf); /* restore my env */
+ /* restore my env */
+ SetEnvironmentVariable("PHP_FCGI_CHILDREN", kid_buf);
goto parent_out;
} else {
diff --git a/sapi/cli/config.w32 b/sapi/cli/config.w32
index 664394c8a6..c6409b59df 100644
--- a/sapi/cli/config.w32
+++ b/sapi/cli/config.w32
@@ -12,6 +12,11 @@ if (PHP_CLI == "yes") {
ADD_FLAG("CFLAGS_CLI", "/D PHP_WIN32_DEBUG_HEAP");
}
ADD_FLAG("LDFLAGS_CLI", "/stack:67108864");
+
+ if (CHECK_LIB("edit_a.lib;edit.lib", "cli", PHP_CLI) &&
+ CHECK_HEADER_ADD_INCLUDE("editline/readline.h", "CFLAGS_CLI")) {
+ ADD_FLAG("CFLAGS_CLI", "/D HAVE_LIBEDIT");
+ }
}
if (PHP_CLI_WIN32 == "yes") {
diff --git a/sapi/cli/tests/cli_process_title_windows.phpt b/sapi/cli/tests/cli_process_title_windows.phpt
index 12eb80756d..4e81b4c634 100644
--- a/sapi/cli/tests/cli_process_title_windows.phpt
+++ b/sapi/cli/tests/cli_process_title_windows.phpt
@@ -21,7 +21,7 @@ if (shell_exec('PowerShell -Help') === NULL)
// cli_set_process_title(). We're only making the API calls to ensure there are
// no warnings/errors.
-$is_windows8 = false;
+$is_windows8_or_above = false;
$ps_output = shell_exec("PowerShell -NoProfile \"(Get-Host).UI.RawUI.WindowTitle\"");
if ($ps_output === null)
{
@@ -31,8 +31,8 @@ if ($ps_output === null)
$ps_output = trim($ps_output);
$end_title_windows8 = ": Windows PowerShell";
-if (($ps_output == "Windows PowerShell") || (strlen($ps_output) > strlen($end_title_windows8) && substr($ps_output,-strlen($end_title_windows8)) === $end_title_windows8))
- $is_windows8 = true;
+if (($ps_output == "Windows PowerShell") || (strlen($ps_output) > strlen($end_title_windows8) && substr($ps_output,-strlen($end_title_windows8)) === $end_title_windows8) || PHP_WINDOWS_VERSION_MAJOR >= 10)
+ $is_windows8_or_above = true;
echo "*** Testing setting the process title ***\n";
@@ -42,7 +42,7 @@ $pid = getmypid();
if (cli_set_process_title($original_title) === true)
echo "Successfully set title\n";
-if ($is_windows8)
+if ($is_windows8_or_above)
{
$loaded_title = $original_title;
}
@@ -82,4 +82,4 @@ else
*** Testing setting the process title ***
Successfully set title
Successfully verified title using get-process
-Successfully verified title using get \ No newline at end of file
+Successfully verified title using get
diff --git a/win32/build/confutils.js b/win32/build/confutils.js
index c2852cfd43..82b7fbc7b2 100644
--- a/win32/build/confutils.js
+++ b/win32/build/confutils.js
@@ -2645,6 +2645,15 @@ function toolset_setup_common_cflags()
if (VCVERS >= 1900) {
ADD_FLAG('CFLAGS', "/guard:cf");
}
+ if (VCVERS >= 1800) {
+ if (PHP_PGI != "yes" && PHP_PGO != "yes") {
+ ADD_FLAG('CFLAGS', "/Zc:inline");
+ }
+ /* We enable /opt:icf only with the debug pack, so /Gw only makes sense there, too. */
+ if (PHP_DEBUG_PACK == "yes") {
+ ADD_FLAG('CFLAGS', "/Gw");
+ }
+ }
}
} else if (CLANG_TOOLSET) {