diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f8a1abca4ec13..df7d66809ab5d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -80,7 +80,7 @@ repository. Mailing list subscription is explained on the [mailing lists page](https://www.php.net/mailing-lists.php). You may also want to read -[The Mysterious PHP RFC Process](https://blogs.oracle.com/opal/entry/the_mysterious_php_rfc_process) +[The Mysterious PHP RFC Process](https://blogs.oracle.com/opal/post/the-mysterious-php-rfc-process-and-how-you-can-change-the-web) for additional notes on the best way to approach submitting an RFC. ## Writing tests diff --git a/NEWS b/NEWS index 17e01da2f80fa..f4c6710df556f 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,74 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.1 +20 Jan 2022, PHP 8.1.2 + +- Core: + . Fixed bug #81216 (Nullsafe operator leaks dynamic property name). (Dmitry) + . Fixed bug #81684 (Using null coalesce assignment with $GLOBALS["x"] produces + opcode error). (ilutov) + . Fixed bug #81656 (GCC-11 silently ignores -R). (Michael Wallner) + . Fixed bug #81683 (Misleading "access type ... must be public" error message + on final or abstract interface methods). (ilutov) + . Fixed bug #81585 (cached_chunks are not counted to real_size on shutdown). + (cmb) + . Fixed bug GH-7757 (Multi-inherited final constant causes fatal error). + (cmb) + . Fixed zend_fibers.c build with ZEND_FIBER_UCONTEXT. (Petr Sumbera) + . Added riscv64 support for fibers. (Jeremie Courreges-Anglas) + +- Filter: + . Fixed FILTER_FLAG_NO_RES_RANGE flag. (Yifan Tong) + +- Hash: + . Fixed bug GH-7759 (Incorrect return types for hash() and hash_hmac()). + (cmb) + . Fixed bug GH-7826 (Inconsistent argument name in hash_hmac_file and + hash_file). (cmb) + +- MBString: + . Fixed bug #81693 (mb_check_encoding(7bit) segfaults). (cmb) + +- MySQLi: + . Fixed bug #81658 (MYSQL_OPT_LOAD_DATA_LOCAL_DIR not available in MariaDB). + (devnexen) + . Introduced MYSQLI_IS_MARIADB. (devnexen) + . Fixed bug GH-7746 (mysqli_sql_exception->getSqlState()). (Kamil Tekiela) + +- MySQLnd: + . Fixed bug where large bigints may be truncated. (Nathan Freeman, cmb) + +- OCI8: + . Fixed bug GH-7765 (php_oci_cleanup_global_handles segfaults at second + call). (cmb) + +- OPcache: + . Fixed bug #81679 (Tracing JIT crashes on reattaching). (cmb) + +- Readline: + . Fixed bug #81598 (Cannot input unicode characters in PHP 8 interactive + shell). (Nikita) + +- Reflection: + . Fixed bug #81681 (ReflectionEnum throwing exceptions). (cmb) + +- PDO_PGSQL: + . Fixed error message allocation of PDO PgSQL. (SATO Kentaro) + +- Sockets: + . Avoid void* arithmetic in sockets/multicast.c on NetBSD. (David Carlier) + . Fixed ext/sockets build on Haiku. (David Carlier) + +- Spl: + . Fixed bug #75917 (SplFileObject::seek broken with CSV flags). (Aliaksandr + Bystry) + . Fixed bug GH-7809 (Cloning a faked SplFileInfo object may segfault). (cmb) + +- Standard: + . Fixed bug GH-7748 (gethostbyaddr outputs binary string). (cmb) + . Fixed bug GH-7815 (php_uname doesn't recognise latest Windows versions). + (David Warner) + +02 Dec 2021, PHP 8.1.1 - IMAP: . Fixed bug #81649 (imap_(un)delete accept sequences, not single numbers). diff --git a/README.md b/README.md index d71e1a42fed42..cda88fb4e7532 100644 --- a/README.md +++ b/README.md @@ -103,8 +103,9 @@ Extension Community Library - [PECL](https://pecl.php.net). ## Contributing -Contributions are most welcome by forking the -[GitHub repository](https://github.com/php/php-src) and sending a pull request. +The PHP source code is located in the Git repository at +[github.com/php/php-src](https://github.com/php/php-src). Contributions are most +welcome by forking the repository and sending a pull request. Discussions are done on GitHub, but depending on the topic can also be relayed to the official PHP developer mailing list internals@lists.php.net. @@ -114,19 +115,15 @@ New features require an RFC and must be accepted by the developers. See [Voting on PHP features](https://wiki.php.net/rfc/voting) for more information on the process. -Bug fixes **do not** require an RFC but require a bug tracker ticket. Open a -ticket at [bugs.php.net](https://bugs.php.net) and reference the bug id using -`#NNNNNN`. +Bug fixes don't require an RFC. If the bug has a GitHub issue, reference it in +the commit message using `GH-NNNNNN`. Use `#NNNNNN` for tickets in the old +[bugs.php.net](https://bugs.php.net) bug tracker. + Fix GH-7815: php_uname doesn't recognise latest Windows versions Fix #55371: get_magic_quotes_gpc() throws deprecation warning - After removing magic quotes, the get_magic_quotes_gpc function caused a - deprecated warning. get_magic_quotes_gpc can be used to detect the - magic_quotes behavior and therefore should not raise a warning at any time. - The patch removes this warning. - -See [Git workflow](https://wiki.php.net/vcs/gitworkflow) for more details on the -pull request workflow. +See [Git workflow](https://wiki.php.net/vcs/gitworkflow) for details on how pull +requests are merged. ### Guidelines for contributors diff --git a/Zend/Optimizer/dce.c b/Zend/Optimizer/dce.c index 0902979ca55fa..087add4cbed66 100644 --- a/Zend/Optimizer/dce.c +++ b/Zend/Optimizer/dce.c @@ -620,7 +620,10 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, bool reorder_d while ((i = zend_bitset_pop_first(ctx.instr_worklist, ctx.instr_worklist_len)) >= 0) { zend_bitset_excl(ctx.instr_dead, i); add_operands_to_worklists(&ctx, &op_array->opcodes[i], &ssa->ops[i], ssa, 1); - if (i < op_array->last && op_array->opcodes[i+1].opcode == ZEND_OP_DATA) { + if (i < op_array->last + && (op_array->opcodes[i+1].opcode == ZEND_OP_DATA + || (op_array->opcodes[i].opcode == ZEND_NEW + && op_array->opcodes[i+1].opcode == ZEND_DO_FCALL))) { zend_bitset_excl(ctx.instr_dead, i+1); add_operands_to_worklists(&ctx, &op_array->opcodes[i+1], &ssa->ops[i+1], ssa, 1); } diff --git a/Zend/Optimizer/dfa_pass.c b/Zend/Optimizer/dfa_pass.c index 75885acfcf488..d0b52fbfcd1bb 100644 --- a/Zend/Optimizer/dfa_pass.c +++ b/Zend/Optimizer/dfa_pass.c @@ -333,7 +333,7 @@ static inline bool can_elide_return_type_check( } static bool opline_supports_assign_contraction( - zend_ssa *ssa, zend_op *opline, int src_var, uint32_t cv_var) { + zend_op_array *op_array, zend_ssa *ssa, zend_op *opline, int src_var, uint32_t cv_var) { if (opline->opcode == ZEND_NEW) { /* see Zend/tests/generators/aborted_yield_during_new.phpt */ return 0; @@ -367,6 +367,13 @@ static bool opline_supports_assign_contraction( return opline->op1_type != IS_CV || opline->op1.var != cv_var; } + if (opline->opcode == ZEND_ASSIGN_OP + && opline->op1_type == IS_CV + && opline->op1.var == cv_var + && zend_may_throw(opline, &ssa->ops[ssa->vars[src_var].definition], op_array, ssa)) { + return 0; + } + return 1; } @@ -741,9 +748,13 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa) uint32_t op_num; zend_op *opline; zend_ssa_op *ssa_op; + bool can_follow = 1; while (next_block_num < ssa->cfg.blocks_count && !(ssa->cfg.blocks[next_block_num].flags & ZEND_BB_REACHABLE)) { + if (ssa->cfg.blocks[next_block_num].flags & ZEND_BB_UNREACHABLE_FREE) { + can_follow = 0; + } next_block_num++; } @@ -755,7 +766,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa) switch (opline->opcode) { case ZEND_JMP: optimize_jmp: - if (block->successors[0] == next_block_num) { + if (block->successors[0] == next_block_num && can_follow) { MAKE_NOP(opline); removed_ops++; goto optimize_nop; @@ -776,7 +787,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa) goto optimize_jmp; } } else { - if (block->successors[0] == next_block_num) { + if (block->successors[0] == next_block_num && can_follow) { take_successor_0(ssa, block_num, block); if (opline->op1_type == IS_CV && (OP1_INFO() & MAY_BE_UNDEF)) { opline->opcode = ZEND_CHECK_VAR; @@ -807,7 +818,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa) goto optimize_nop; } } else if (block->successors_count == 2) { - if (block->successors[0] == next_block_num) { + if (block->successors[0] == next_block_num && can_follow) { take_successor_0(ssa, block_num, block); if (opline->op1_type == IS_CV && (OP1_INFO() & MAY_BE_UNDEF)) { opline->opcode = ZEND_CHECK_VAR; @@ -841,7 +852,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa) } else if (block->successors_count == 2) { if (block->successors[0] == block->successors[1]) { take_successor_0(ssa, block_num, block); - if (block->successors[0] == next_block_num) { + if (block->successors[0] == next_block_num && can_follow) { if (opline->op1_type == IS_CV && (OP1_INFO() & MAY_BE_UNDEF)) { opline->opcode = ZEND_CHECK_VAR; opline->op2.num = 0; @@ -1353,7 +1364,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx && !ssa->vars[src_var].phi_use_chain && !ssa->vars[src_var].sym_use_chain && opline_supports_assign_contraction( - ssa, &op_array->opcodes[ssa->vars[src_var].definition], + op_array, ssa, &op_array->opcodes[ssa->vars[src_var].definition], src_var, opline->result.var) && !variable_defined_or_used_in_range(ssa, EX_VAR_TO_NUM(opline->result.var), ssa->vars[src_var].definition+1, op_1) @@ -1510,7 +1521,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx && !ssa->vars[src_var].phi_use_chain && !ssa->vars[src_var].sym_use_chain && opline_supports_assign_contraction( - ssa, &op_array->opcodes[ssa->vars[src_var].definition], + op_array, ssa, &op_array->opcodes[ssa->vars[src_var].definition], src_var, opline->op1.var) && !variable_defined_or_used_in_range(ssa, EX_VAR_TO_NUM(opline->op1.var), ssa->vars[src_var].definition+1, op_1) diff --git a/Zend/Optimizer/pass1.c b/Zend/Optimizer/pass1.c index 110babf3e95d4..695348a389179 100644 --- a/Zend/Optimizer/pass1.c +++ b/Zend/Optimizer/pass1.c @@ -104,33 +104,9 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) break; case ZEND_ASSIGN_OP: - if (opline->op2_type == IS_CONST) { - if (opline->extended_value == ZEND_ADD - || opline->extended_value == ZEND_SUB - || opline->extended_value == ZEND_MUL - || opline->extended_value == ZEND_DIV - || opline->extended_value == ZEND_POW) { - if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { - /* don't optimize if it should produce a runtime numeric string error */ - if (is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0)) { - convert_scalar_to_number(&ZEND_OP2_LITERAL(opline)); - } - } - } else if (opline->extended_value == ZEND_MOD - || opline->extended_value == ZEND_SL - || opline->extended_value == ZEND_SR) { - zval *op2 = &ZEND_OP2_LITERAL(opline); - if (Z_TYPE_P(op2) != IS_LONG) { - if (!zend_is_op_long_compatible(op2)) { - break; - } - convert_to_long(op2); - } - } else if (opline->extended_value == ZEND_CONCAT) { - if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) { - convert_to_string(&ZEND_OP2_LITERAL(opline)); - } - } + if (opline->extended_value == ZEND_CONCAT && opline->op2_type == IS_CONST + && Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) { + convert_to_string(&ZEND_OP2_LITERAL(opline)); } break; diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index e341cbf1cc9bc..f468273e41dfa 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -1526,6 +1526,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o if (opline->opcode == ZEND_PRE_INC_OBJ || opline->opcode == ZEND_PRE_DEC_OBJ) { SET_RESULT(result, &tmp2); + zval_ptr_dtor_nogc(&tmp1); } else { SET_RESULT(result, &tmp1); } @@ -2258,7 +2259,9 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var, removed_ops = remove_call(ctx, opline, ssa_op); } else if (opline->opcode == ZEND_TYPE_CHECK && (opline->op1_type & (IS_VAR|IS_TMP_VAR)) - && !value_known(&ctx->values[ssa_op->op1_use])) { + && (!value_known(&ctx->values[ssa_op->op1_use]) + || IS_PARTIAL_ARRAY(&ctx->values[ssa_op->op1_use]) + || IS_PARTIAL_OBJECT(&ctx->values[ssa_op->op1_use]))) { /* For TYPE_CHECK we may compute the result value without knowing the * operand, based on type inference information. Make sure the operand is * freed and leave further cleanup to DCE. */ diff --git a/Zend/Optimizer/zend_func_infos.h b/Zend/Optimizer/zend_func_infos.h index 0e18481f40738..d0d54989dc71d 100644 --- a/Zend/Optimizer/zend_func_infos.h +++ b/Zend/Optimizer/zend_func_infos.h @@ -171,9 +171,9 @@ static const func_info_t func_infos[] = { F1("gmp_sqrtrem", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_OBJECT), F1("gmp_rootrem", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_OBJECT), F1("gmp_gcdext", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_OBJECT), - F1("hash", MAY_BE_STRING|MAY_BE_FALSE), + F1("hash", MAY_BE_STRING), F1("hash_file", MAY_BE_STRING|MAY_BE_FALSE), - F1("hash_hmac", MAY_BE_STRING|MAY_BE_FALSE), + F1("hash_hmac", MAY_BE_STRING), F1("hash_hmac_file", MAY_BE_STRING|MAY_BE_FALSE), F1("hash_init", MAY_BE_OBJECT), F1("hash_final", MAY_BE_STRING), diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index d26e74720d839..9ff4f28ff9ec9 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -1041,8 +1041,6 @@ static int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ss ZEND_API int zend_inference_propagate_range(const zend_op_array *op_array, zend_ssa *ssa, zend_op *opline, zend_ssa_op* ssa_op, int var, zend_ssa_range *tmp) { - zend_long op1_min, op2_min, op1_max, op2_max; - tmp->underflow = 0; tmp->overflow = 0; switch (opline->opcode) { @@ -1070,8 +1068,8 @@ ZEND_API int zend_inference_propagate_range(const zend_op_array *op_array, zend_ tmp->min = ZEND_LONG_MIN; tmp->max = ZEND_LONG_MAX; } else { - op1_min = OP1_MIN_RANGE(); - op1_max = OP1_MAX_RANGE(); + zend_long op1_min = OP1_MIN_RANGE(); + zend_long op1_max = OP1_MAX_RANGE(); tmp->min = ~op1_max; tmp->max = ~op1_min; } @@ -1104,144 +1102,6 @@ ZEND_API int zend_inference_propagate_range(const zend_op_array *op_array, zend_ } } break; - case ZEND_BOOL: - case ZEND_JMPZ_EX: - case ZEND_JMPNZ_EX: - if (ssa_op->result_def == var) { - if (OP1_HAS_RANGE()) { - op1_min = OP1_MIN_RANGE(); - op1_max = OP1_MAX_RANGE(); - tmp->min = (op1_min > 0 || op1_max < 0); - tmp->max = (op1_min != 0 || op1_max != 0); - return 1; - } else { - tmp->min = 0; - tmp->max = 1; - return 1; - } - } - break; - case ZEND_BOOL_NOT: - if (ssa_op->result_def == var) { - if (OP1_HAS_RANGE()) { - op1_min = OP1_MIN_RANGE(); - op1_max = OP1_MAX_RANGE(); - tmp->min = (op1_min == 0 && op1_max == 0); - tmp->max = (op1_min <= 0 && op1_max >= 0); - return 1; - } else { - tmp->min = 0; - tmp->max = 1; - return 1; - } - } - break; - case ZEND_BOOL_XOR: - if (ssa_op->result_def == var) { - if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { - op1_min = OP1_MIN_RANGE(); - op2_min = OP2_MIN_RANGE(); - op1_max = OP1_MAX_RANGE(); - op2_max = OP2_MAX_RANGE(); - op1_min = (op1_min > 0 || op1_max < 0); - op1_max = (op1_min != 0 || op1_max != 0); - op2_min = (op2_min > 0 || op2_max < 0); - op2_max = (op2_min != 0 || op2_max != 0); - tmp->min = 0; - tmp->max = 1; - if (op1_min == op1_max && op2_min == op2_max) { - if (op1_min == op2_min) { - tmp->max = 0; - } else { - tmp->min = 1; - } - } - return 1; - } else { - tmp->min = 0; - tmp->max = 1; - return 1; - } - } - break; - case ZEND_IS_IDENTICAL: - case ZEND_IS_EQUAL: - if (ssa_op->result_def == var) { - if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { - op1_min = OP1_MIN_RANGE(); - op2_min = OP2_MIN_RANGE(); - op1_max = OP1_MAX_RANGE(); - op2_max = OP2_MAX_RANGE(); - - tmp->min = (op1_min == op1_max && - op2_min == op2_max && - op1_min == op2_max); - tmp->max = (op1_min <= op2_max && op1_max >= op2_min); - return 1; - } else { - tmp->min = 0; - tmp->max = 1; - return 1; - } - } - break; - case ZEND_IS_NOT_IDENTICAL: - case ZEND_IS_NOT_EQUAL: - if (ssa_op->result_def == var) { - if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { - op1_min = OP1_MIN_RANGE(); - op2_min = OP2_MIN_RANGE(); - op1_max = OP1_MAX_RANGE(); - op2_max = OP2_MAX_RANGE(); - - tmp->min = (op1_min > op2_max || op1_max < op2_min); - tmp->max = (op1_min != op1_max || - op2_min != op2_max || - op1_min != op2_max); - return 1; - } else { - tmp->min = 0; - tmp->max = 1; - return 1; - } - } - break; - case ZEND_IS_SMALLER: - if (ssa_op->result_def == var) { - if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { - op1_min = OP1_MIN_RANGE(); - op2_min = OP2_MIN_RANGE(); - op1_max = OP1_MAX_RANGE(); - op2_max = OP2_MAX_RANGE(); - - tmp->min = op1_max < op2_min; - tmp->max = op1_min < op2_max; - return 1; - } else { - tmp->min = 0; - tmp->max = 1; - return 1; - } - } - break; - case ZEND_IS_SMALLER_OR_EQUAL: - if (ssa_op->result_def == var) { - if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { - op1_min = OP1_MIN_RANGE(); - op2_min = OP2_MIN_RANGE(); - op1_max = OP1_MAX_RANGE(); - op2_max = OP2_MAX_RANGE(); - - tmp->min = op1_max <= op2_min; - tmp->max = op1_min <= op2_max; - return 1; - } else { - tmp->min = 0; - tmp->max = 1; - return 1; - } - } - break; case ZEND_QM_ASSIGN: case ZEND_JMP_SET: case ZEND_COALESCE: @@ -1267,13 +1127,6 @@ ZEND_API int zend_inference_propagate_range(const zend_op_array *op_array, zend_ } } break; - case ZEND_ASSERT_CHECK: - if (ssa_op->result_def == var) { - tmp->min = 0; - tmp->max = 1; - return 1; - } - break; case ZEND_SEND_VAR: if (ssa_op->op1_def == var) { if (ssa_op->op1_def >= 0) { @@ -1454,12 +1307,6 @@ ZEND_API int zend_inference_propagate_range(const zend_op_array *op_array, zend_ tmp->max = ZEND_LONG_MAX; tmp->overflow = 0; return 1; - } else if (mask == MAY_BE_BOOL) { - tmp->underflow = 0; - tmp->min = 0; - tmp->max = 1; - tmp->overflow = 0; - return 1; } } } @@ -2388,6 +2235,25 @@ static uint32_t zend_fetch_prop_type(const zend_script *script, zend_property_in return zend_convert_type(script, prop_info->type, pce); } +static bool result_may_be_separated(zend_ssa *ssa, zend_ssa_op *ssa_op) +{ + int tmp_var = ssa_op->result_def; + + if (ssa->vars[tmp_var].use_chain >= 0 + && !ssa->vars[tmp_var].phi_use_chain) { + zend_ssa_op *use_op = &ssa->ops[ssa->vars[tmp_var].use_chain]; + + /* TODO: analize instructions between ssa_op and use_op */ + if (use_op == ssa_op + 1) { + if ((use_op->op1_use == tmp_var && use_op->op1_use_chain < 0) + || (use_op->op2_use == tmp_var && use_op->op2_use_chain < 0)) { + return 0; + } + } + } + return 1; +} + static zend_always_inline int _zend_update_type_info( const zend_op_array *op_array, zend_ssa *ssa, @@ -2614,7 +2480,7 @@ static zend_always_inline int _zend_update_type_info( ssa, opline->extended_value, t1, t2, opline->opcode == ZEND_ASSIGN_OP ? ssa_op->op1_def : -1, optimization_level); if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY)) { - tmp |= MAY_BE_RC1; + tmp |= MAY_BE_RC1 | MAY_BE_RCN; } if (tmp & (MAY_BE_OBJECT|MAY_BE_RESOURCE)) { tmp |= MAY_BE_RC1 | MAY_BE_RCN; @@ -3202,7 +3068,9 @@ static zend_always_inline int _zend_update_type_info( arr_type = RES_USE_INFO(); } tmp = MAY_BE_RC1|MAY_BE_ARRAY|arr_type; - if (opline->op1_type != IS_UNUSED) { + if (opline->op1_type != IS_UNUSED + && (opline->op2_type == IS_UNUSED + || (t2 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_RESOURCE|MAY_BE_STRING)))) { tmp |= assign_dim_array_result_type(arr_type, t2, t1, opline->op2_type); if (opline->extended_value & ZEND_ARRAY_ELEMENT_REF) { tmp |= MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; @@ -3491,11 +3359,11 @@ static zend_always_inline int _zend_update_type_info( if (prop_info) { /* FETCH_OBJ_R/IS for plain property increments reference counter, so it can't be 1 */ - if (ce && !ce->create_object) { + if (ce && !ce->create_object && !result_may_be_separated(ssa, ssa_op)) { tmp &= ~MAY_BE_RC1; } } else { - if (ce && !ce->create_object && !ce->__get) { + if (ce && !ce->create_object && !ce->__get && !result_may_be_separated(ssa, ssa_op)) { tmp &= ~MAY_BE_RC1; } } @@ -3521,7 +3389,9 @@ static zend_always_inline int _zend_update_type_info( if (opline->result_type == IS_VAR) { tmp |= MAY_BE_REF | MAY_BE_INDIRECT; } else { - tmp &= ~MAY_BE_RC1; + if (!result_may_be_separated(ssa, ssa_op)) { + tmp &= ~MAY_BE_RC1; + } if (opline->opcode == ZEND_FETCH_STATIC_PROP_IS) { tmp |= MAY_BE_UNDEF; } diff --git a/Zend/Optimizer/zend_ssa.c b/Zend/Optimizer/zend_ssa.c index cd0e179cd89d4..725fb0921813b 100644 --- a/Zend/Optimizer/zend_ssa.c +++ b/Zend/Optimizer/zend_ssa.c @@ -334,10 +334,6 @@ static void place_essa_pis( if (Z_TYPE_P(zv) == IS_LONG) { add_val2 = Z_LVAL_P(zv); - } else if (Z_TYPE_P(zv) == IS_FALSE) { - add_val2 = 0; - } else if (Z_TYPE_P(zv) == IS_TRUE) { - add_val2 = 1; } else { var1 = -1; } @@ -355,10 +351,6 @@ static void place_essa_pis( zval *zv = CRT_CONSTANT_EX(op_array, (opline-1), (opline-1)->op1); if (Z_TYPE_P(zv) == IS_LONG) { add_val1 = Z_LVAL_P(CRT_CONSTANT_EX(op_array, (opline-1), (opline-1)->op1)); - } else if (Z_TYPE_P(zv) == IS_FALSE) { - add_val1 = 0; - } else if (Z_TYPE_P(zv) == IS_TRUE) { - add_val1 = 1; } else { var2 = -1; } diff --git a/Zend/asm/jump_riscv64_sysv_elf_gas.S b/Zend/asm/jump_riscv64_sysv_elf_gas.S new file mode 100644 index 0000000000000..5417e5d5e3498 --- /dev/null +++ b/Zend/asm/jump_riscv64_sysv_elf_gas.S @@ -0,0 +1,150 @@ +/* + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ +/******************************************************* + * * + * ------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * + * ------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * + * ------------------------------------------------- * + * | fs0 | fs1 | fs2 | fs3 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * + * ------------------------------------------------- * + * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * + * ------------------------------------------------- * + * | fs4 | fs5 | fs6 | fs7 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * + * ------------------------------------------------- * + * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * + * ------------------------------------------------- * + * | fs8 | fs9 | fs10 | fs11 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | * + * ------------------------------------------------- * + * | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| * + * ------------------------------------------------- * + * | s0 | s1 | s2 | s3 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * + * ------------------------------------------------- * + * | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| * + * ------------------------------------------------- * + * | s4 | s5 | s6 | s7 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | * + * ------------------------------------------------- * + * | 0xa0| 0xa4| 0xa8| 0xac| 0xb0| 0xb4| 0xb8| 0xbc| * + * ------------------------------------------------- * + * | s8 | s9 | s10 | s11 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 48 | 49 | 50 | 51 | | | | | * + * ------------------------------------------------- * + * | 0xc0| 0xc4| 0xc8| 0xcc| | | | | * + * ------------------------------------------------- * + * | ra | pc | | | * + * ------------------------------------------------- * + * * + *******************************************************/ + +.file "jump_riscv64_sysv_elf_gas.S" +.text +.align 1 +.global jump_fcontext +.type jump_fcontext, %function +jump_fcontext: + # prepare stack for GP + FPU + addi sp, sp, -0xd0 + + # save fs0 - fs11 + fsd fs0, 0x00(sp) + fsd fs1, 0x08(sp) + fsd fs2, 0x10(sp) + fsd fs3, 0x18(sp) + fsd fs4, 0x20(sp) + fsd fs5, 0x28(sp) + fsd fs6, 0x30(sp) + fsd fs7, 0x38(sp) + fsd fs8, 0x40(sp) + fsd fs9, 0x48(sp) + fsd fs10, 0x50(sp) + fsd fs11, 0x58(sp) + + # save s0-s11, ra + sd s0, 0x60(sp) + sd s1, 0x68(sp) + sd s2, 0x70(sp) + sd s3, 0x78(sp) + sd s4, 0x80(sp) + sd s5, 0x88(sp) + sd s6, 0x90(sp) + sd s7, 0x98(sp) + sd s8, 0xa0(sp) + sd s9, 0xa8(sp) + sd s10, 0xb0(sp) + sd s11, 0xb8(sp) + sd ra, 0xc0(sp) + + # save RA as PC + sd ra, 0xc8(sp) + + # store SP (pointing to context-data) in A2 + mv a2, sp + + # restore SP (pointing to context-data) from A0 + mv sp, a0 + + # load fs0 - fs11 + fld fs0, 0x00(sp) + fld fs1, 0x08(sp) + fld fs2, 0x10(sp) + fld fs3, 0x18(sp) + fld fs4, 0x20(sp) + fld fs5, 0x28(sp) + fld fs6, 0x30(sp) + fld fs7, 0x38(sp) + fld fs8, 0x40(sp) + fld fs9, 0x48(sp) + fld fs10, 0x50(sp) + fld fs11, 0x58(sp) + + # load s0-s11,ra + ld s0, 0x60(sp) + ld s1, 0x68(sp) + ld s2, 0x70(sp) + ld s3, 0x78(sp) + ld s4, 0x80(sp) + ld s5, 0x88(sp) + ld s6, 0x90(sp) + ld s7, 0x98(sp) + ld s8, 0xa0(sp) + ld s9, 0xa8(sp) + ld s10, 0xb0(sp) + ld s11, 0xb8(sp) + ld ra, 0xc0(sp) + + # return transfer_t from jump + # pass transfer_t as first arg in context function + # a0 == FCTX, a1 == DATA + mv a0, a2 + + # load pc + ld a2, 0xc8(sp) + + # restore stack from GP + FPU + addi sp, sp, 0xd0 + + jr a2 +.size jump_fcontext,.-jump_fcontext +# Mark that we don't need executable stack. +.section .note.GNU-stack,"",%progbits diff --git a/Zend/asm/make_riscv64_sysv_elf_gas.S b/Zend/asm/make_riscv64_sysv_elf_gas.S new file mode 100644 index 0000000000000..5322e0fdbdec7 --- /dev/null +++ b/Zend/asm/make_riscv64_sysv_elf_gas.S @@ -0,0 +1,91 @@ +/* + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ +/******************************************************* + * * + * ------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * + * ------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * + * ------------------------------------------------- * + * | fs0 | fs1 | fs2 | fs3 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * + * ------------------------------------------------- * + * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * + * ------------------------------------------------- * + * | fs4 | fs5 | fs6 | fs7 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * + * ------------------------------------------------- * + * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * + * ------------------------------------------------- * + * | fs8 | fs9 | fs10 | fs11 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | * + * ------------------------------------------------- * + * | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| * + * ------------------------------------------------- * + * | s0 | s1 | s2 | s3 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * + * ------------------------------------------------- * + * | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| * + * ------------------------------------------------- * + * | s4 | s5 | s6 | s7 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | * + * ------------------------------------------------- * + * | 0xa0| 0xa4| 0xa8| 0xac| 0xb0| 0xb4| 0xb8| 0xbc| * + * ------------------------------------------------- * + * | s8 | s9 | s10 | s11 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 48 | 49 | 50 | 51 | | | | | * + * ------------------------------------------------- * + * | 0xc0| 0xc4| 0xc8| 0xcc| | | | | * + * ------------------------------------------------- * + * | ra | pc | | | * + * ------------------------------------------------- * + * * + *******************************************************/ + +.file "make_riscv64_sysv_elf_gas.S" +.text +.align 1 +.global make_fcontext +.type make_fcontext, %function +make_fcontext: + # shift address in a0 (allocated stack) to lower 16 byte boundary + andi a0, a0, ~0xF + + # reserve space for context-data on context-stack + addi a0, a0, -0xd0 + + # third arg of make_fcontext() == address of context-function + # store address as a PC to jump in + sd a2, 0xc8(a0) + + # save address of finish as return-address for context-function + # will be entered after context-function returns (RA register) + lla a4, finish + sd a4, 0xc0(a0) + + ret // return pointer to context-data (a0) + +finish: + # exit code is zero + li a0, 0 + # exit application + tail _exit@plt + +.size make_fcontext,.-make_fcontext +# Mark that we don't need executable stack. +.section .note.GNU-stack,"",%progbits diff --git a/Zend/tests/assign_op_type_error.phpt b/Zend/tests/assign_op_type_error.phpt new file mode 100644 index 0000000000000..5f175613e20b8 --- /dev/null +++ b/Zend/tests/assign_op_type_error.phpt @@ -0,0 +1,57 @@ +--TEST-- +TypeError for compound assignment operations +--FILE-- +getMessage(), "\n"; +} +try { + $x -= "1"; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + $x *= "1"; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + $x /= "1"; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + $x **= "1"; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + $x %= "1"; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + $x <<= "1"; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +try { + $x >>= "1"; +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Unsupported operand types: array + string +Unsupported operand types: array - string +Unsupported operand types: array * string +Unsupported operand types: array / string +Unsupported operand types: array ** string +Unsupported operand types: array % string +Unsupported operand types: array << string +Unsupported operand types: array >> string diff --git a/Zend/tests/bug71871.phpt b/Zend/tests/bug71871.phpt index 981e7519c7652..9d93f5dd9a6f1 100644 --- a/Zend/tests/bug71871.phpt +++ b/Zend/tests/bug71871.phpt @@ -9,4 +9,4 @@ interface test { ?> --EXPECTF-- -Fatal error: Access type for interface method test::test() must be public in %s on line %d +Fatal error: Interface method test::test() must not be final in %s on line %d diff --git a/Zend/tests/bug71871_2.phpt b/Zend/tests/bug71871_2.phpt index 2781a8d495503..d1ed08f0b6cfb 100644 --- a/Zend/tests/bug71871_2.phpt +++ b/Zend/tests/bug71871_2.phpt @@ -9,4 +9,4 @@ interface test { ?> --EXPECTF-- -Fatal error: Access type for interface method test::test() must be public in %s on line %d +Fatal error: Interface method test::test() must not be abstract in %s on line %d diff --git a/Zend/tests/bug81216.phpt b/Zend/tests/bug81216.phpt new file mode 100644 index 0000000000000..0ec08d5aeca84 --- /dev/null +++ b/Zend/tests/bug81216.phpt @@ -0,0 +1,10 @@ +--TEST-- +Bug #81216: Nullsafe operator leaks dynamic property name +--FILE-- +{$str . "bar"}; +?> +DONE +--EXPECT-- +DONE diff --git a/Zend/tests/bug81216_2.phpt b/Zend/tests/bug81216_2.phpt new file mode 100644 index 0000000000000..8bf347a80e57c --- /dev/null +++ b/Zend/tests/bug81216_2.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #81216_2: Nullsafe operator leaks dynamic property name +--FILE-- +x; +var_dump($a); +?> +--EXPECT-- +array(2) { + [0]=> + NULL + [1]=> + NULL +} diff --git a/Zend/tests/bug81684.phpt b/Zend/tests/bug81684.phpt new file mode 100644 index 0000000000000..e47056187a765 --- /dev/null +++ b/Zend/tests/bug81684.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #81684: ??= on $GLOBALS produces an invalid opcode +--FILE-- + +--EXPECT-- +string(1) "x" +Done. diff --git a/Zend/tests/constants/final_constants/final_const13.phpt b/Zend/tests/constants/final_constants/final_const13.phpt new file mode 100644 index 0000000000000..5e19e8a212695 --- /dev/null +++ b/Zend/tests/constants/final_constants/final_const13.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug GH-7757 (Multi-inherited final constant causes fatal error) +--FILE-- + +--EXPECT-- diff --git a/Zend/tests/falsetoarray_002.phpt b/Zend/tests/falsetoarray_002.phpt new file mode 100644 index 0000000000000..c01b799545965 --- /dev/null +++ b/Zend/tests/falsetoarray_002.phpt @@ -0,0 +1,15 @@ +--TEST-- +Autovivification of false to array with data clobbering by error handler +--FILE-- + +--EXPECT-- +Err: Automatic conversion of false to array is deprecated +string(0) "" diff --git a/Zend/tests/falsetoarray_003.phpt b/Zend/tests/falsetoarray_003.phpt new file mode 100644 index 0000000000000..11b32771e1fc1 --- /dev/null +++ b/Zend/tests/falsetoarray_003.phpt @@ -0,0 +1,16 @@ +--TEST-- +Autovivification of false to array with data clobbering by error handler +--FILE-- + +DONE +--EXPECTF-- +Err: Implicit conversion from float %f to int loses precision +Err: Undefined array key %i +DONE diff --git a/Zend/tests/lc_ctype_inheritance.phpt b/Zend/tests/lc_ctype_inheritance.phpt index 8971ff1969723..8c968f0615e6e 100644 --- a/Zend/tests/lc_ctype_inheritance.phpt +++ b/Zend/tests/lc_ctype_inheritance.phpt @@ -16,8 +16,8 @@ var_dump(setlocale(LC_CTYPE, "de_DE", "de-DE") !== false); var_dump(bin2hex(strtoupper("\xe4"))); var_dump(preg_match('/\w/', "\xe4")); ?> ---EXPECT-- -string(1) "C" +--EXPECTF-- +string(%d) "C%r(\.UTF-8)?%r" string(2) "e4" int(0) bool(true) diff --git a/Zend/tests/objects_034.phpt b/Zend/tests/objects_034.phpt new file mode 100644 index 0000000000000..5594e756aface --- /dev/null +++ b/Zend/tests/objects_034.phpt @@ -0,0 +1,37 @@ +--TEST-- +Array object clobbering by user error handler +--FILE-- + +--EXPECT-- +NULL +NULL +NULL diff --git a/Zend/tests/objects_035.phpt b/Zend/tests/objects_035.phpt new file mode 100644 index 0000000000000..1ca5a761a26c4 --- /dev/null +++ b/Zend/tests/objects_035.phpt @@ -0,0 +1,27 @@ +--TEST-- +Array object clobbering by user error handler +--FILE-- + +DONE +--EXPECT-- +DONE diff --git a/Zend/tests/str_offset_008.phpt b/Zend/tests/str_offset_008.phpt new file mode 100644 index 0000000000000..e99e46e59e749 --- /dev/null +++ b/Zend/tests/str_offset_008.phpt @@ -0,0 +1,18 @@ +--TEST-- +string offset 008 indirect string modification by error handler +--FILE-- + +--EXPECT-- +Err: Undefined variable $b +Err: String offset cast occurred +string(1) "x" +int(8) diff --git a/Zend/zend.h b/Zend/zend.h index b4cabb7ae7601..c13ebae6a689e 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.1-dev" +#define ZEND_VERSION "4.1.2" #define ZEND_ENGINE_3 diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 6af234b4d75a8..04b1a4ff19d02 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2304,10 +2304,10 @@ void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent) #endif memset(heap->free_slot, 0, sizeof(heap->free_slot)); #if ZEND_MM_STAT || ZEND_MM_LIMIT - heap->real_size = ZEND_MM_CHUNK_SIZE; + heap->real_size = (heap->cached_chunks_count + 1) * ZEND_MM_CHUNK_SIZE; #endif #if ZEND_MM_STAT - heap->real_peak = ZEND_MM_CHUNK_SIZE; + heap->real_peak = (heap->cached_chunks_count + 1) * ZEND_MM_CHUNK_SIZE; #endif heap->chunks_count = 1; heap->peak_chunks_count = 1; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index a36a986402944..7a338775174e0 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2258,11 +2258,11 @@ static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */ ZEND_ASSERT(count >= offset); for (i = offset; i < count; ++i) { - opline = get_next_op(); - memcpy(opline, &oplines[i], sizeof(zend_op)); - if (opline->opcode == ZEND_JMP_NULL) { - uint32_t opnum = get_next_op_number() - 1; - zend_stack_push(&CG(short_circuiting_opnums), &opnum); + if (EXPECTED(oplines[i].opcode != ZEND_NOP)) { + opline = get_next_op(); + memcpy(opline, &oplines[i], sizeof(zend_op)); + } else { + opline = CG(active_op_array)->opcodes + oplines[i].extended_value; } } @@ -2890,11 +2890,31 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0); zend_separate_if_call_and_write(&obj_node, obj_ast, type); if (nullsafe) { - /* We will push to the short_circuiting_opnums stack in zend_delayed_compile_end(). */ - opline = zend_delayed_emit_op(NULL, ZEND_JMP_NULL, &obj_node, NULL); - if (opline->op1_type == IS_CONST) { - Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1)); + if (obj_node.op_type == IS_TMP_VAR) { + /* Flush delayed oplines */ + zend_op *opline = NULL, *oplines = zend_stack_base(&CG(delayed_oplines_stack)); + uint32_t var = obj_node.u.op.var; + uint32_t count = zend_stack_count(&CG(delayed_oplines_stack)); + uint32_t i = count; + + while (i > 0 && oplines[i-1].result_type == IS_TMP_VAR && oplines[i-1].result.var == var) { + i--; + if (oplines[i].op1_type == IS_TMP_VAR) { + var = oplines[i].op1.var; + } else { + break; + } + } + for (; i < count; ++i) { + if (oplines[i].opcode != ZEND_NOP) { + opline = get_next_op(); + memcpy(opline, &oplines[i], sizeof(zend_op)); + oplines[i].opcode = ZEND_NOP; + oplines[i].extended_value = opline - CG(active_op_array)->opcodes; + } + } } + zend_emit_jmp_null(&obj_node); } } @@ -7034,10 +7054,18 @@ static zend_string *zend_begin_method_decl(zend_op_array *op_array, zend_string } if (in_interface) { - if (!(fn_flags & ZEND_ACC_PUBLIC) || (fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) { + if (!(fn_flags & ZEND_ACC_PUBLIC)) { zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method " "%s::%s() must be public", ZSTR_VAL(ce->name), ZSTR_VAL(name)); } + if (fn_flags & ZEND_ACC_FINAL) { + zend_error_noreturn(E_COMPILE_ERROR, "Interface method " + "%s::%s() must not be final", ZSTR_VAL(ce->name), ZSTR_VAL(name)); + } + if (fn_flags & ZEND_ACC_ABSTRACT) { + zend_error_noreturn(E_COMPILE_ERROR, "Interface method " + "%s::%s() must not be abstract", ZSTR_VAL(ce->name), ZSTR_VAL(name)); + } op_array->fn_flags |= ZEND_ACC_ABSTRACT; } @@ -8981,7 +9009,9 @@ static void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */ /* Reproduce some of the zend_compile_assign() opcode fixup logic here. */ opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; - switch (var_ast->kind) { + /* Treat $GLOBALS['x'] assignment like assignment to variable. */ + zend_ast_kind kind = is_global_var_fetch(var_ast) ? ZEND_AST_VAR : var_ast->kind; + switch (kind) { case ZEND_AST_VAR: zend_emit_op_tmp(&assign_node, ZEND_ASSIGN, &var_node_w, &default_node); break; diff --git a/Zend/zend_cpuinfo.c b/Zend/zend_cpuinfo.c index 57889bb3f4ce3..08843a9401f46 100644 --- a/Zend/zend_cpuinfo.c +++ b/Zend/zend_cpuinfo.c @@ -75,7 +75,7 @@ static void __zend_cpuid(uint32_t func, uint32_t subfunc, zend_cpu_info *cpuinfo #if defined(__i386__) || defined(__x86_64__) /* Function based on compiler-rt implementation. */ -static unsigned get_xcr0_eax() { +static unsigned get_xcr0_eax(void) { # if defined(__GNUC__) || defined(__clang__) // Check xgetbv; this uses a .byte sequence instead of the instruction // directly because older assemblers do not include support for xgetbv and @@ -90,7 +90,7 @@ static unsigned get_xcr0_eax() { # endif } -static bool is_avx_supported() { +static bool is_avx_supported(void) { if (!(cpuinfo.ecx & ZEND_CPU_FEATURE_AVX)) { /* No support for AVX */ return 0; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 450432691c391..a245db9835379 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1394,9 +1394,9 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_string_offset zend_type_error("Cannot access offset of type %s on string", zend_zval_type_name(offset)); } -static zend_never_inline void zend_assign_to_object_dim(zval *object, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline void zend_assign_to_object_dim(zend_object *obj, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC) { - Z_OBJ_HT_P(object)->write_dimension(Z_OBJ_P(object), dim, value); + obj->handlers->write_dimension(obj, dim, value); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); @@ -1425,17 +1425,21 @@ static zend_always_inline int zend_binary_op(zval *ret, zval *op1, zval *op2 OPL return zend_binary_ops[opcode - ZEND_ADD](ret, op1, op2); } -static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval *property OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline void zend_binary_assign_op_obj_dim(zend_object *obj, zval *property OPLINE_DC EXECUTE_DATA_DC) { zval *value; zval *z; zval rv, res; + GC_ADDREF(obj); + if (property && UNEXPECTED(Z_ISUNDEF_P(property))) { + property = ZVAL_UNDEFINED_OP2(); + } value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); - if ((z = Z_OBJ_HT_P(object)->read_dimension(Z_OBJ_P(object), property, BP_VAR_R, &rv)) != NULL) { + if ((z = obj->handlers->read_dimension(obj, property, BP_VAR_R, &rv)) != NULL) { if (zend_binary_op(&res, z, value OPLINE_CC) == SUCCESS) { - Z_OBJ_HT_P(object)->write_dimension(Z_OBJ_P(object), property, &res); + obj->handlers->write_dimension(obj, property, &res); } if (z == &rv) { zval_ptr_dtor(&rv); @@ -1451,6 +1455,9 @@ static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval * } } FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } static zend_never_inline void zend_binary_assign_op_typed_ref(zend_reference *ref, zval *value OPLINE_DC EXECUTE_DATA_DC) @@ -2464,16 +2471,17 @@ static zend_always_inline void zend_fetch_dimension_address(zval *result, zval * } ZVAL_UNDEF(result); } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + GC_ADDREF(obj); if (ZEND_CONST_COND(dim_type == IS_CV, dim != NULL) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) { dim = ZVAL_UNDEFINED_OP2(); - } - if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + } else if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - retval = Z_OBJ_HT_P(container)->read_dimension(Z_OBJ_P(container), dim, type, result); + retval = obj->handlers->read_dimension(obj, dim, type, result); if (UNEXPECTED(retval == &EG(uninitialized_zval))) { - zend_class_entry *ce = Z_OBJCE_P(container); + zend_class_entry *ce = obj->ce; ZVAL_NULL(result); zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name)); @@ -2484,7 +2492,7 @@ static zend_always_inline void zend_fetch_dimension_address(zval *result, zval * retval = result; } if (Z_TYPE_P(retval) != IS_OBJECT) { - zend_class_entry *ce = Z_OBJCE_P(container); + zend_class_entry *ce = obj->ce; zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name)); } } else if (UNEXPECTED(Z_REFCOUNT_P(retval) == 1)) { @@ -2497,18 +2505,32 @@ static zend_always_inline void zend_fetch_dimension_address(zval *result, zval * ZEND_ASSERT(EG(exception) && "read_dimension() returned NULL without exception"); ZVAL_UNDEF(result); } + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else { if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { if (type != BP_VAR_W && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - if (Z_TYPE_P(container) == IS_FALSE) { - zend_false_to_array_deprecated(); - } if (type != BP_VAR_UNSET) { - array_init(container); + HashTable *ht = zend_new_array(0); + zend_uchar old_type = Z_TYPE_P(container); + + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto return_null; + } + } goto fetch_from_array; } else { + if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) { + zend_false_to_array_deprecated(); + } return_null: /* for read-mode only */ if (ZEND_CONST_COND(dim_type == IS_CV, dim != NULL) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) { @@ -2653,13 +2675,16 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z ZVAL_CHAR(result, c); } } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + + GC_ADDREF(obj); if (ZEND_CONST_COND(dim_type == IS_CV, 1) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) { dim = ZVAL_UNDEFINED_OP2(); } if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - retval = Z_OBJ_HT_P(container)->read_dimension(Z_OBJ_P(container), dim, type, result); + retval = obj->handlers->read_dimension(obj, dim, type, result); ZEND_ASSERT(result != NULL); if (retval) { @@ -2671,6 +2696,9 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z } else { ZVAL_NULL(result); } + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else { if (type != BP_VAR_IS && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { container = ZVAL_UNDEFINED_OP1(); diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 92ae9b8837cb7..dd06f86ae8da6 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -32,6 +32,10 @@ # include #endif +#ifdef ZEND_FIBER_UCONTEXT +# include +#endif + #ifndef ZEND_WIN32 # include # include @@ -118,7 +122,6 @@ static zend_always_inline void zend_fiber_restore_vm_state(zend_fiber_vm_state * } #ifdef ZEND_FIBER_UCONTEXT -# include ZEND_TLS zend_fiber_transfer *transfer_data; #else /* boost_context_data is our customized definition of struct transfer_t as diff --git a/Zend/zend_gdb.c b/Zend/zend_gdb.c index e38e0023095fd..02afb6bc6f7bc 100644 --- a/Zend/zend_gdb.c +++ b/Zend/zend_gdb.c @@ -25,6 +25,11 @@ #include #include +#if defined(__FreeBSD__) +# include +# include +#endif + enum { ZEND_GDBJIT_NOACTION, ZEND_GDBJIT_REGISTER, @@ -105,6 +110,7 @@ ZEND_API void zend_gdb_unregister_all(void) ZEND_API bool zend_gdb_present(void) { bool ret = 0; +#if defined(__linux__) /* netbsd while having this procfs part, does not hold the tracer pid */ int fd = open("/proc/self/status", O_RDONLY); if (fd > 0) { @@ -136,6 +142,17 @@ ZEND_API bool zend_gdb_present(void) close(fd); } +#elif defined(__FreeBSD__) + struct kinfo_proc *proc = kinfo_getproc(getpid()); + + if (proc) { + if ((proc->ki_flag & P_TRACED) != 0) { + struct kinfo_proc *dbg = kinfo_getproc(proc->ki_tracer); + + ret = (dbg && strstr(dbg->ki_comm, "gdb")); + } + } +#endif return ret; } diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 4903ef4b3828b..020c5e6553920 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1605,7 +1605,7 @@ static bool do_inherit_constant_check( } zend_class_constant *old_constant = Z_PTR_P(zv); - if ((ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_FINAL)) { + if (parent_constant->ce != old_constant->ce && (ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_FINAL)) { zend_error_noreturn(E_COMPILE_ERROR, "%s::%s cannot override final constant %s::%s", ZSTR_VAL(old_constant->ce->name), ZSTR_VAL(name), ZSTR_VAL(parent_constant->ce->name), ZSTR_VAL(name) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 0a516f691901a..d178b9b506fe8 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2662,6 +2662,15 @@ ZEND_API void zend_update_current_locale(void) /* {{{ */ } /* }}} */ +ZEND_API void zend_reset_lc_ctype_locale(void) +{ + /* Use the C.UTF-8 locale so that readline can process UTF-8 input, while not interfering + * with single-byte locale-dependent functions used by PHP. */ + if (!setlocale(LC_CTYPE, "C.UTF-8")) { + setlocale(LC_CTYPE, "C"); + } +} + static zend_always_inline void zend_str_tolower_impl(char *dest, const char *str, size_t length) /* {{{ */ { unsigned char *p = (unsigned char*)str; unsigned char *q = (unsigned char*)dest; diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 5610d34dedb3b..2044b20b2be6e 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -472,6 +472,8 @@ ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len); ZEND_API void zend_update_current_locale(void); +ZEND_API void zend_reset_lc_ctype_locale(void); + /* The offset in bytes between the value and type fields of a zval */ #define ZVAL_OFFSETOF_TYPE \ (offsetof(zval, u1.type_info) - offsetof(zval, value)) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index ac537f6ccdfd3..6920bc7632a2f 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1150,6 +1150,7 @@ ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, OP) USE_OPLINE zval *var_ptr; zval *value, *container, *dim; + HashTable *ht; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); @@ -1157,19 +1158,20 @@ ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, OP) if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { ZEND_VM_C_LABEL(assign_dim_op_array): SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); ZEND_VM_C_LABEL(assign_dim_op_new_array): dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP2_TYPE == IS_UNUSED) { - var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { zend_cannot_add_element(); ZEND_VM_C_GOTO(assign_dim_op_ret_null); } } else { if (OP2_TYPE == IS_CONST) { - var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); } else { - var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); } if (UNEXPECTED(!var_ptr)) { ZEND_VM_C_GOTO(assign_dim_op_ret_null); @@ -1203,19 +1205,30 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array): } if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - dim = GET_OP2_ZVAL_PTR(BP_VAR_R); + zend_object *obj = Z_OBJ_P(container); + + dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + zend_uchar old_type; + if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - if (Z_TYPE_P(container) == IS_FALSE) { + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + ZEND_VM_C_GOTO(assign_dim_op_ret_null); + } } - ZVAL_ARR(container, zend_new_array(8)); ZEND_VM_C_GOTO(assign_dim_op_new_array); } else { dim = GET_OP2_ZVAL_PTR(BP_VAR_R); @@ -2577,15 +2590,29 @@ ZEND_VM_C_LABEL(try_assign_dim_array): } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = GET_OP2_ZVAL_PTR(BP_VAR_R); - value = GET_OP_DATA_ZVAL_PTR_DEREF(BP_VAR_R); + zend_object *obj = Z_OBJ_P(object_ptr); - if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); + if (OP2_TYPE == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = GET_OP_DATA_ZVAL_PTR_UNDEF(BP_VAR_R); + if (OP_DATA_TYPE == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (OP_DATA_TYPE & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); FREE_OP_DATA(); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (OP2_TYPE == IS_UNUSED) { zend_use_new_element_for_string(); @@ -2598,10 +2625,6 @@ ZEND_VM_C_LABEL(try_assign_dim_array): FREE_OP_DATA(); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -2609,7 +2632,18 @@ ZEND_VM_C_LABEL(try_assign_dim_array): FREE_OP_DATA(); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + ZEND_VM_C_GOTO(assign_dim_error); + } + } ZEND_VM_C_GOTO(try_assign_dim_array); } } else { @@ -9636,7 +9670,10 @@ ZEND_VM_C_LABEL(fetch_dim_r_index_array): if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { offset = Z_LVAL_P(dim); } else { - offset = zval_get_long_ex(dim, /* is_strict */ true); + SAVE_OPLINE(); + zend_fetch_dimension_address_read_R(container, dim, OP2_TYPE OPLINE_CC EXECUTE_DATA_CC); + FREE_OP1(); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ht = Z_ARRVAL_P(container); ZEND_HASH_INDEX_FIND(ht, offset, value, ZEND_VM_C_LABEL(fetch_dim_r_index_undef)); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 6e7ef05d68585..42f5310cd026e 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -8318,7 +8318,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { offset = Z_LVAL_P(dim); } else { - offset = zval_get_long_ex(dim, /* is_strict */ true); + SAVE_OPLINE(); + zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR|IS_CV) OPLINE_CC EXECUTE_DATA_CC); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ht = Z_ARRVAL_P(container); ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); @@ -16126,7 +16129,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { offset = Z_LVAL_P(dim); } else { - offset = zval_get_long_ex(dim, /* is_strict */ true); + SAVE_OPLINE(); + zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ht = Z_ARRVAL_P(container); ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); @@ -16178,7 +16184,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { offset = Z_LVAL_P(dim); } else { - offset = zval_get_long_ex(dim, /* is_strict */ true); + SAVE_OPLINE(); + zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR|IS_CV) OPLINE_CC EXECUTE_DATA_CC); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ht = Z_ARRVAL_P(container); ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); @@ -22392,6 +22401,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H USE_OPLINE zval *var_ptr; zval *value, *container, *dim; + HashTable *ht; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -22399,19 +22409,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); assign_dim_op_new_array: dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_UNUSED) { - var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { zend_cannot_add_element(); goto assign_dim_op_ret_null; } } else { if (IS_CONST == IS_CONST) { - var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); } else { - var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); } if (UNEXPECTED(!var_ptr)) { goto assign_dim_op_ret_null; @@ -22445,19 +22456,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CONST_H } if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + zend_uchar old_type; + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - if (Z_TYPE_P(container) == IS_FALSE) { + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } } - ZVAL_ARR(container, zend_new_array(8)); goto assign_dim_op_new_array; } else { dim = RT_CONSTANT(opline, opline->op2); @@ -23383,14 +23405,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = RT_CONSTANT(opline, opline->op2); - value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -23403,10 +23439,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -23414,7 +23446,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -23499,15 +23542,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -23520,10 +23577,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -23531,7 +23584,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -23616,15 +23680,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -23637,10 +23715,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -23648,7 +23722,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -23733,14 +23818,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -23753,10 +23852,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -23764,7 +23859,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_D UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -24945,6 +25051,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_ USE_OPLINE zval *var_ptr; zval *value, *container, *dim; + HashTable *ht; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -24952,19 +25059,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); assign_dim_op_new_array: dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { zend_cannot_add_element(); goto assign_dim_op_ret_null; } } else { if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); } else { - var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); } if (UNEXPECTED(!var_ptr)) { goto assign_dim_op_ret_null; @@ -24998,19 +25106,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_TMPVAR_ } if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + zend_uchar old_type; + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - if (Z_TYPE_P(container) == IS_FALSE) { + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } } - ZVAL_ARR(container, zend_new_array(8)); goto assign_dim_op_new_array; } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); @@ -25941,14 +26060,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_object *obj = Z_OBJ_P(object_ptr); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); @@ -25961,10 +26094,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -25972,7 +26101,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -26057,15 +26197,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); @@ -26078,10 +26232,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -26089,7 +26239,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -26174,15 +26335,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); @@ -26195,10 +26370,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -26206,7 +26377,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -26291,14 +26473,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); @@ -26311,10 +26507,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -26322,7 +26514,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_ UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -27136,6 +27339,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_ USE_OPLINE zval *var_ptr; zval *value, *container, *dim; + HashTable *ht; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -27143,19 +27347,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); assign_dim_op_new_array: dim = NULL; if (IS_UNUSED == IS_UNUSED) { - var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { zend_cannot_add_element(); goto assign_dim_op_ret_null; } } else { if (IS_UNUSED == IS_CONST) { - var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); } else { - var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); } if (UNEXPECTED(!var_ptr)) { goto assign_dim_op_ret_null; @@ -27189,19 +27394,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_UNUSED_ } if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + dim = NULL; if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + zend_uchar old_type; + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - if (Z_TYPE_P(container) == IS_FALSE) { + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } } - ZVAL_ARR(container, zend_new_array(8)); goto assign_dim_op_new_array; } else { dim = NULL; @@ -27331,14 +27547,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; - value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -27351,10 +27581,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -27362,7 +27588,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -27447,15 +27684,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -27468,10 +27719,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -27479,7 +27726,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -27564,15 +27822,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; - value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -27585,10 +27857,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -27596,7 +27864,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -27681,14 +27960,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; - value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -27701,10 +27994,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -27712,7 +28001,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_ UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -28875,6 +29175,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND USE_OPLINE zval *var_ptr; zval *value, *container, *dim; + HashTable *ht; SAVE_OPLINE(); container = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); @@ -28882,19 +29183,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); assign_dim_op_new_array: dim = EX_VAR(opline->op2.var); if (IS_CV == IS_UNUSED) { - var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { zend_cannot_add_element(); goto assign_dim_op_ret_null; } } else { if (IS_CV == IS_CONST) { - var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); } else { - var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); } if (UNEXPECTED(!var_ptr)) { goto assign_dim_op_ret_null; @@ -28928,19 +29230,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_VAR_CV_HAND } if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(container); + + dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + zend_uchar old_type; + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - if (Z_TYPE_P(container) == IS_FALSE) { + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } } - ZVAL_ARR(container, zend_new_array(8)); goto assign_dim_op_new_array; } else { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); @@ -29866,14 +30179,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -29886,10 +30213,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -29897,7 +30220,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -29982,15 +30316,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -30003,10 +30351,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -30014,7 +30358,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -30099,15 +30454,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -30120,10 +30489,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -30131,7 +30496,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -30216,14 +30592,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -30236,10 +30626,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -30247,7 +30633,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -39481,6 +39878,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA USE_OPLINE zval *var_ptr; zval *value, *container, *dim; + HashTable *ht; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); @@ -39488,19 +39886,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); assign_dim_op_new_array: dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_UNUSED) { - var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { zend_cannot_add_element(); goto assign_dim_op_ret_null; } } else { if (IS_CONST == IS_CONST) { - var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); } else { - var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); } if (UNEXPECTED(!var_ptr)) { goto assign_dim_op_ret_null; @@ -39534,19 +39933,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CONST_HA } if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + zend_uchar old_type; + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - if (Z_TYPE_P(container) == IS_FALSE) { + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } } - ZVAL_ARR(container, zend_new_array(8)); goto assign_dim_op_new_array; } else { dim = RT_CONSTANT(opline, opline->op2); @@ -40735,14 +41145,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = RT_CONSTANT(opline, opline->op2); - value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -40755,10 +41179,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -40766,7 +41186,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -40851,15 +41282,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -40872,10 +41317,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -40883,7 +41324,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -40968,15 +41420,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -40989,10 +41455,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -41000,7 +41462,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -41085,14 +41558,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = RT_CONSTANT(opline, opline->op2); - value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = RT_CONSTANT(opline, opline->op2); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CONST == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CONST == IS_UNUSED) { zend_use_new_element_for_string(); @@ -41105,10 +41592,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -41116,7 +41599,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DA UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -42443,7 +42937,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { offset = Z_LVAL_P(dim); } else { - offset = zval_get_long_ex(dim, /* is_strict */ true); + SAVE_OPLINE(); + zend_fetch_dimension_address_read_R(container, dim, IS_CONST OPLINE_CC EXECUTE_DATA_CC); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ht = Z_ARRVAL_P(container); ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); @@ -42495,7 +42992,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_INDEX_ if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) { offset = Z_LVAL_P(dim); } else { - offset = zval_get_long_ex(dim, /* is_strict */ true); + SAVE_OPLINE(); + zend_fetch_dimension_address_read_R(container, dim, (IS_TMP_VAR|IS_VAR|IS_CV) OPLINE_CC EXECUTE_DATA_CC); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ht = Z_ARRVAL_P(container); ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); @@ -43113,6 +43613,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H USE_OPLINE zval *var_ptr; zval *value, *container, *dim; + HashTable *ht; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); @@ -43120,19 +43621,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); assign_dim_op_new_array: dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { - var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { zend_cannot_add_element(); goto assign_dim_op_ret_null; } } else { if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { - var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); } else { - var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); } if (UNEXPECTED(!var_ptr)) { goto assign_dim_op_ret_null; @@ -43166,19 +43668,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_TMPVAR_H } if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + zend_uchar old_type; + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - if (Z_TYPE_P(container) == IS_FALSE) { + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } } - ZVAL_ARR(container, zend_new_array(8)); goto assign_dim_op_new_array; } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); @@ -44366,14 +44879,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_object *obj = Z_OBJ_P(object_ptr); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); @@ -44386,10 +44913,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -44397,7 +44920,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -44482,15 +45016,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); @@ -44503,10 +45051,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -44514,7 +45058,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -44599,15 +45154,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); @@ -44620,10 +45189,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -44631,7 +45196,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -44716,14 +45292,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_use_new_element_for_string(); @@ -44736,10 +45326,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -44747,7 +45333,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_D UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -45880,6 +46477,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H USE_OPLINE zval *var_ptr; zval *value, *container, *dim; + HashTable *ht; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); @@ -45887,19 +46485,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); assign_dim_op_new_array: dim = NULL; if (IS_UNUSED == IS_UNUSED) { - var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { zend_cannot_add_element(); goto assign_dim_op_ret_null; } } else { if (IS_UNUSED == IS_CONST) { - var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); } else { - var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); } if (UNEXPECTED(!var_ptr)) { goto assign_dim_op_ret_null; @@ -45933,19 +46532,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_UNUSED_H } if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(container); + dim = NULL; if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + zend_uchar old_type; + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - if (Z_TYPE_P(container) == IS_FALSE) { + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } } - ZVAL_ARR(container, zend_new_array(8)); goto assign_dim_op_new_array; } else { dim = NULL; @@ -46203,14 +46813,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; - value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -46223,10 +46847,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -46234,7 +46854,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -46319,15 +46950,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -46340,10 +46985,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -46351,7 +46992,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -46436,15 +47088,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; - value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -46457,10 +47123,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -46468,7 +47130,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -46553,14 +47226,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = NULL; - value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = NULL; + if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_UNUSED == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_UNUSED == IS_UNUSED) { zend_use_new_element_for_string(); @@ -46573,10 +47260,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -46584,7 +47267,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_D UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -48150,6 +48844,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL USE_OPLINE zval *var_ptr; zval *value, *container, *dim; + HashTable *ht; SAVE_OPLINE(); container = EX_VAR(opline->op1.var); @@ -48157,19 +48852,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { assign_dim_op_array: SEPARATE_ARRAY(container); + ht = Z_ARRVAL_P(container); assign_dim_op_new_array: dim = EX_VAR(opline->op2.var); if (IS_CV == IS_UNUSED) { - var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); + var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); if (UNEXPECTED(!var_ptr)) { zend_cannot_add_element(); goto assign_dim_op_ret_null; } } else { if (IS_CV == IS_CONST) { - var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); } else { - var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim EXECUTE_DATA_CC); + var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); } if (UNEXPECTED(!var_ptr)) { goto assign_dim_op_ret_null; @@ -48203,19 +48899,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_OP_SPEC_CV_CV_HANDL } if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(container); + + dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC); + zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { + zend_uchar old_type; + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { ZVAL_UNDEFINED_OP1(); } - if (Z_TYPE_P(container) == IS_FALSE) { + ht = zend_new_array(8); + old_type = Z_TYPE_P(container); + ZVAL_ARR(container, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_op_ret_null; + } } - ZVAL_ARR(container, zend_new_array(8)); goto assign_dim_op_new_array; } else { dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); @@ -49399,14 +50106,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = RT_CONSTANT((opline+1), (opline+1)->op1); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = RT_CONSTANT((opline+1), (opline+1)->op1); + if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CONST & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -49419,10 +50140,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -49430,7 +50147,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -49515,15 +50243,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_TMP_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -49536,10 +50278,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -49547,7 +50285,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -49632,15 +50381,29 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + + value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); + if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_VAR & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -49653,10 +50416,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -49664,7 +50423,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { @@ -49749,14 +50519,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ } } if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - dim = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); - value = _get_zval_ptr_cv_deref_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); + zend_object *obj = Z_OBJ_P(object_ptr); - if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { + GC_ADDREF(obj); + dim = EX_VAR(opline->op2.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { + dim = ZVAL_UNDEFINED_OP2(); + } else if (IS_CV == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { dim++; } - zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); + value = EX_VAR((opline+1)->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { + value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); + } else if (IS_CV & (IS_CV|IS_VAR)) { + ZVAL_DEREF(value); + } + + zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); + + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (IS_CV == IS_UNUSED) { zend_use_new_element_for_string(); @@ -49769,10 +50553,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); - } - if (Z_ISREF_P(orig_object_ptr) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { @@ -49780,7 +50560,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_ UNDEF_RESULT(); } else { - ZVAL_ARR(object_ptr, zend_new_array(8)); + HashTable *ht = zend_new_array(8); + zend_uchar old_type = Z_TYPE_P(object_ptr); + + ZVAL_ARR(object_ptr, ht); + if (UNEXPECTED(old_type == IS_FALSE)) { + GC_ADDREF(ht); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(ht) == 0)) { + zend_array_destroy(ht); + goto assign_dim_error; + } + } goto try_assign_dim_array; } } else { diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 343447a8d8983..45d559f26c7c4 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -2688,7 +2688,8 @@ function gen_vm($def, $skel) { fputs($f, "ZEND_API zend_uchar zend_get_opcode_id(const char *name, size_t length) {\n"); fputs($f, "\tzend_uchar opcode;\n"); fputs($f, "\tfor (opcode = 0; opcode < (sizeof(zend_vm_opcodes_names) / sizeof(zend_vm_opcodes_names[0])) - 1; opcode++) {\n"); - fputs($f, "\t\tif (strncmp(zend_vm_opcodes_names[opcode], name, length) == 0) {\n"); + fputs($f, "\t\tconst char *opcode_name = zend_vm_opcodes_names[opcode];\n"); + fputs($f, "\t\tif (opcode_name && strncmp(opcode_name, name, length) == 0) {\n"); fputs($f, "\t\t\treturn opcode;\n"); fputs($f, "\t\t}\n"); fputs($f, "\t}\n"); diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 7f88f9e84b690..085c473d59578 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -449,7 +449,8 @@ ZEND_API uint32_t ZEND_FASTCALL zend_get_opcode_flags(zend_uchar opcode) { ZEND_API zend_uchar zend_get_opcode_id(const char *name, size_t length) { zend_uchar opcode; for (opcode = 0; opcode < (sizeof(zend_vm_opcodes_names) / sizeof(zend_vm_opcodes_names[0])) - 1; opcode++) { - if (strncmp(zend_vm_opcodes_names[opcode], name, length) == 0) { + const char *opcode_name = zend_vm_opcodes_names[opcode]; + if (opcode_name && strncmp(opcode_name, name, length) == 0) { return opcode; } } diff --git a/appveyor/build.bat b/appveyor/build.bat index 3593228389e0f..a6b34a0314f63 100644 --- a/appveyor/build.bat +++ b/appveyor/build.bat @@ -1,6 +1,6 @@ @echo off -set SDK_REMOTE=https://github.com/Microsoft/php-sdk-binary-tools.git +set SDK_REMOTE=https://github.com/php/php-sdk-binary-tools.git set SDK_BRANCH=%PHP_BUILD_SDK_BRANCH% set SDK_RUNNER=%PHP_BUILD_CACHE_SDK_DIR%\phpsdk-%PHP_BUILD_CRT%-%PLATFORM%.bat diff --git a/build/php.m4 b/build/php.m4 index 4f64f669eb970..01b8250598191 100644 --- a/build/php.m4 +++ b/build/php.m4 @@ -279,25 +279,25 @@ dnl dnl Checks for -R, etc. switch. dnl AC_DEFUN([PHP_RUNPATH_SWITCH],[ -AC_MSG_CHECKING([if compiler supports -R]) -AC_CACHE_VAL(php_cv_cc_dashr,[ +AC_MSG_CHECKING([if compiler supports -Wl,-rpath,]) +AC_CACHE_VAL(php_cv_cc_rpath,[ SAVE_LIBS=$LIBS - LIBS="-R /usr/$PHP_LIBDIR $LIBS" - AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],[php_cv_cc_dashr=yes],[php_cv_cc_dashr=no]) + LIBS="-Wl,-rpath,/usr/$PHP_LIBDIR $LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],[php_cv_cc_rpath=yes],[php_cv_cc_rpath=no]) LIBS=$SAVE_LIBS]) -AC_MSG_RESULT([$php_cv_cc_dashr]) -if test $php_cv_cc_dashr = "yes"; then - ld_runpath_switch=-R +AC_MSG_RESULT([$php_cv_cc_rpath]) +if test $php_cv_cc_rpath = "yes"; then + ld_runpath_switch=-Wl,-rpath, else - AC_MSG_CHECKING([if compiler supports -Wl,-rpath,]) - AC_CACHE_VAL(php_cv_cc_rpath,[ + AC_MSG_CHECKING([if compiler supports -R]) + AC_CACHE_VAL(php_cv_cc_dashr,[ SAVE_LIBS=$LIBS - LIBS="-Wl,-rpath,/usr/$PHP_LIBDIR $LIBS" - AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],[php_cv_cc_rpath=yes],[php_cv_cc_rpath=no]) + LIBS="-R /usr/$PHP_LIBDIR $LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],[php_cv_cc_dashr=yes],[php_cv_cc_dashr=no]) LIBS=$SAVE_LIBS]) - AC_MSG_RESULT([$php_cv_cc_rpath]) - if test $php_cv_cc_rpath = "yes"; then - ld_runpath_switch=-Wl,-rpath, + AC_MSG_RESULT([$php_cv_cc_dashr]) + if test $php_cv_cc_dashr = "yes"; then + ld_runpath_switch=-R else dnl Something innocuous. ld_runpath_switch=-L diff --git a/configure.ac b/configure.ac index e6270a7523533..5d4f682876190 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.1.1-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.2],[https://bugs.php.net],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER @@ -1201,6 +1201,7 @@ AS_CASE([$host_cpu], [arm*], [fiber_cpu="arm32"], [ppc64*|powerpc64*], [fiber_cpu="ppc64"], [ppc*|powerpc*], [fiber_cpu="ppc32"], + [riscv64*], [fiber_cpu="riscv64"], [s390x*], [fiber_cpu="s390x"], [mips64*], [fiber_cpu="mips64"], [mips*], [fiber_cpu="mips32"], @@ -1220,6 +1221,7 @@ AS_CASE([$fiber_cpu], [arm32], [fiber_asm_file_prefix="arm_aapcs"], [ppc64], [fiber_asm_file_prefix="ppc64_sysv"], [ppc32], [fiber_asm_file_prefix="ppc32_sysv"], + [riscv64], [fiber_asm_file_prefix="riscv64_sysv"], [s390x], [fiber_asm_file_prefix="s390x_sysv"], [mips64], [fiber_asm_file_prefix="mips64_n64"], [mips32], [fiber_asm_file_prefix="mips32_o32"], diff --git a/ext/com_dotnet/php_com_dotnet_internal.h b/ext/com_dotnet/php_com_dotnet_internal.h index de5f1a5462db0..77ba7cdb60e15 100644 --- a/ext/com_dotnet/php_com_dotnet_internal.h +++ b/ext/com_dotnet/php_com_dotnet_internal.h @@ -72,7 +72,7 @@ zend_class_entry *php_com_variant_class_entry, *php_com_exception_class_entry, * zend_object* php_com_object_new(zend_class_entry *ce); zend_object* php_com_object_clone(zend_object *object); void php_com_object_free_storage(zend_object *object); -zend_object_handlers php_com_object_handlers; +extern zend_object_handlers php_com_object_handlers; void php_com_object_enable_event_sink(php_com_dotnet_object *obj, int enable); /* com_saproxy.c */ diff --git a/ext/curl/sync-constants.php b/ext/curl/sync-constants.php index 2db773d5f80a1..035dbcf6a237d 100755 --- a/ext/curl/sync-constants.php +++ b/ext/curl/sync-constants.php @@ -12,7 +12,7 @@ const SOURCE_FILE = __DIR__ . '/interface.c'; -const MIN_SUPPORTED_CURL_VERSION = '7.15.5'; +const MIN_SUPPORTED_CURL_VERSION = '7.29.0'; const IGNORED_CONSTANTS = [ 'CURLOPT_PROGRESSDATA' diff --git a/ext/curl/tests/bug76675.phpt b/ext/curl/tests/bug76675.phpt index 8f31aa5eed60f..02cdfe4d5710f 100644 --- a/ext/curl/tests/bug76675.phpt +++ b/ext/curl/tests/bug76675.phpt @@ -2,6 +2,8 @@ Bug #76675 (Segfault with H2 server push write/writeheader handlers) --EXTENSIONS-- curl +--XFAIL-- +http2.golang.org/serverpush is gone --SKIPIF-- --FILE-- --FILE-- = 0xfe80 && ip[0] <= 0xfebf) - || ((ip[0] == 0x2001 && ip[1] == 0x0db8) || (ip[1] >= 0x0010 && ip[1] <= 0x001f)) + || (ip[0] == 0x2001 && (ip[1] == 0x0db8 || (ip[1] >= 0x0010 && ip[1] <= 0x001f))) || (ip[0] == 0x3ff3) ) { RETURN_VALIDATION_FAILED diff --git a/ext/filter/tests/bug47435.phpt b/ext/filter/tests/bug47435.phpt index 1be5c96dba152..b035bc0a5f69f 100644 --- a/ext/filter/tests/bug47435.phpt +++ b/ext/filter/tests/bug47435.phpt @@ -14,6 +14,10 @@ var_dump(filter_var("fe80:5:6::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)); var_dump(filter_var("fe80:5:6::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE)); var_dump(filter_var("2001:0db8::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)); var_dump(filter_var("2001:0db8::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE)); +var_dump(filter_var("2001:0010::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)); +var_dump(filter_var("2001:0010::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE)); +var_dump(filter_var("240b:0010::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)); +var_dump(filter_var("240b:0010::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE)); var_dump(filter_var("5f::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)); var_dump(filter_var("5f::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE)); var_dump(filter_var("3ff3::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)); @@ -30,6 +34,10 @@ string(11) "fe80:5:6::1" bool(false) string(12) "2001:0db8::1" bool(false) +string(12) "2001:0010::1" +bool(false) +string(12) "240b:0010::1" +string(12) "240b:0010::1" string(5) "5f::1" bool(false) string(7) "3ff3::1" diff --git a/ext/hash/hash.stub.php b/ext/hash/hash.stub.php index cbe0ed555966c..6795ecaa87c2f 100644 --- a/ext/hash/hash.stub.php +++ b/ext/hash/hash.stub.php @@ -3,16 +3,16 @@ /** @generate-class-entries */ /** @refcount 1 */ -function hash(string $algo, string $data, bool $binary = false, array $options = []): string|false {} +function hash(string $algo, string $data, bool $binary = false, array $options = []): string {} /** @refcount 1 */ function hash_file(string $algo, string $filename, bool $binary = false, array $options = []): string|false {} /** @refcount 1 */ -function hash_hmac(string $algo, string $data, string $key, bool $binary = false): string|false {} +function hash_hmac(string $algo, string $data, string $key, bool $binary = false): string {} /** @refcount 1 */ -function hash_hmac_file(string $algo, string $data, string $key, bool $binary = false): string|false {} +function hash_hmac_file(string $algo, string $filename, string $key, bool $binary = false): string|false {} /** @refcount 1 */ function hash_init(string $algo, int $flags = 0, string $key = "", array $options = []): HashContext {} diff --git a/ext/hash/hash_arginfo.h b/ext/hash/hash_arginfo.h index 0b9d151b31051..8ce7ba03aa519 100644 --- a/ext/hash/hash_arginfo.h +++ b/ext/hash/hash_arginfo.h @@ -1,7 +1,7 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: d0ed07f608581a5700a10ec53a817ca788ef9638 */ + * Stub hash: 8b5131fd7bd88d1ec0211bcfcb5a4854418aa3c8 */ -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_hash, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_hash, 0, 2, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, algo, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, binary, _IS_BOOL, 0, "false") @@ -15,14 +15,19 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_hash_file, 0, 2, MAY_BE_STRING|M ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "[]") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_hash_hmac, 0, 3, MAY_BE_STRING|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_hash_hmac, 0, 3, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, algo, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, binary, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO() -#define arginfo_hash_hmac_file arginfo_hash_hmac +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_hash_hmac_file, 0, 3, MAY_BE_STRING|MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, algo, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, binary, _IS_BOOL, 0, "false") +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_hash_init, 0, 1, HashContext, 0) ZEND_ARG_TYPE_INFO(0, algo, IS_STRING, 0) diff --git a/ext/hash/tests/hash_hmac_file_error.phpt b/ext/hash/tests/hash_hmac_file_error.phpt index 7cbc347691202..3a4d85ee7e35b 100644 --- a/ext/hash/tests/hash_hmac_file_error.phpt +++ b/ext/hash/tests/hash_hmac_file_error.phpt @@ -43,4 +43,4 @@ hash_hmac_file(): Argument #1 ($algo) must be a valid cryptographic hashing algo hash_hmac_file(): Argument #1 ($algo) must be a valid cryptographic hashing algorithm -- Testing hash_hmac_file() function with bad path -- -hash_hmac_file(): Argument #2 ($data) must not contain any null bytes +hash_hmac_file(): Argument #2 ($filename) must not contain any null bytes diff --git a/ext/mbstring/libmbfl/mbfl/mbfl_convert.c b/ext/mbstring/libmbfl/mbfl/mbfl_convert.c index dda978a71223b..f6e860a35aead 100644 --- a/ext/mbstring/libmbfl/mbfl/mbfl_convert.c +++ b/ext/mbstring/libmbfl/mbfl/mbfl_convert.c @@ -307,7 +307,8 @@ const struct mbfl_convert_vtbl* mbfl_convert_filter_get_vtbl(const mbfl_encoding from = &mbfl_encoding_8bit; } else if (from->no_encoding == mbfl_no_encoding_base64 || from->no_encoding == mbfl_no_encoding_qprint || - from->no_encoding == mbfl_no_encoding_uuencode) { + from->no_encoding == mbfl_no_encoding_uuencode || + from->no_encoding == mbfl_no_encoding_7bit) { to = &mbfl_encoding_8bit; } diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 92a3d865bbd1d..a9bbb3e47e1a5 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -2491,6 +2491,23 @@ MBSTRING_API HashTable *php_mb_convert_encoding_recursive(HashTable *input, cons } /* }}} */ +static void remove_non_encodings_from_elist(const mbfl_encoding **elist, size_t *size) +{ + /* mbstring supports some 'text encodings' which aren't really text encodings + * at all, but really 'byte encodings', like Base64, QPrint, and so on. + * These should never be returned by `mb_detect_encoding`. */ + int shift = 0; + for (int i = 0; i < *size; i++) { + const mbfl_encoding *encoding = elist[i]; + if (encoding->no_encoding <= mbfl_no_encoding_charset_min) { + shift++; /* Remove this encoding from the list */ + } else if (shift) { + elist[i - shift] = encoding; + } + } + *size -= shift; +} + /* {{{ Returns converted string in desired encoding */ PHP_FUNCTION(mb_convert_encoding) { @@ -2531,6 +2548,10 @@ PHP_FUNCTION(mb_convert_encoding) free_from_encodings = 0; } + if (num_from_encodings > 1) { + remove_non_encodings_from_elist(from_encodings, &num_from_encodings); + } + if (!num_from_encodings) { efree(ZEND_VOIDP(from_encodings)); zend_argument_value_error(3, "must specify at least one encoding"); @@ -2664,23 +2685,6 @@ PHP_FUNCTION(mb_strtolower) } /* }}} */ -static void remove_non_encodings_from_elist(const mbfl_encoding **elist, size_t *size) -{ - /* mbstring supports some 'text encodings' which aren't really text encodings - * at all, but really 'byte encodings', like Base64, QPrint, and so on. - * These should never be returned by `mb_detect_encoding`. */ - int shift = 0; - for (int i = 0; i < *size; i++) { - const mbfl_encoding *encoding = elist[i]; - if (encoding->no_encoding <= mbfl_no_encoding_charset_min) { - shift++; /* Remove this encoding from the list */ - } else if (shift) { - elist[i - shift] = encoding; - } - } - *size -= shift; -} - /* {{{ Encodings of the given string is returned (as a string) */ PHP_FUNCTION(mb_detect_encoding) { diff --git a/ext/mbstring/tests/bug81693.phpt b/ext/mbstring/tests/bug81693.phpt new file mode 100644 index 0000000000000..ae52453f8765d --- /dev/null +++ b/ext/mbstring/tests/bug81693.phpt @@ -0,0 +1,10 @@ +--TEST-- +Bug #81693 (mb_check_encoding(7bit) segfaults) +--EXTENSIONS-- +mbstring +--FILE-- + +--EXPECT-- +bool(true) diff --git a/ext/mbstring/tests/mb_convert_encoding.phpt b/ext/mbstring/tests/mb_convert_encoding.phpt index 257873f313079..2c8353e638fe4 100644 --- a/ext/mbstring/tests/mb_convert_encoding.phpt +++ b/ext/mbstring/tests/mb_convert_encoding.phpt @@ -9,33 +9,24 @@ mbstring.language=Japanese 'JIS', 1=>'UTF-8', 2=>'EUC-JP', 3=>'SJIS'); +$a = ['JIS', 'UTF-8', 'EUC-JP', 'SJIS']; $s = $jis; $s = bin2hex(mb_convert_encoding($s, 'EUC-JP', $a)); print("EUC-JP: $s\n"); // EUC-JP @@ -69,6 +59,8 @@ $s = $euc_jp; $s = mb_convert_encoding($s, 'JIS', $a); print("JIS: ".base64_encode($s)."\n"); // JIS +// Regression test for bug #81676 +echo "UTF-8: " . mb_convert_encoding('test', 'UTF-8', mb_list_encodings()), "\n"; // Using Detect Order echo "== DETECT ORDER ==\n"; @@ -117,6 +109,7 @@ JIS: GyRCRnxLXDhsJUYlLSU5JUgkRyQ5ISMbKEIwMTIzNBskQiM1IzYjNyM4IzkhIxsoQg== EUC-JP: c6fccbdcb8eca5c6a5ada5b9a5c8a4c7a4b9a1a33031323334a3b5a3b6a3b7a3b8a3b9a1a3 SJIS: k/qWe4zqg2WDTINYg2eCxYK3gUIwMTIzNIJUglWCVoJXgliBQg== JIS: GyRCRnxLXDhsJUYlLSU5JUgkRyQ5ISMbKEIwMTIzNBskQiM1IzYjNyM4IzkhIxsoQg== +UTF-8: test == DETECT ORDER == EUC-JP: c6fccbdcb8eca5c6a5ada5b9a5c8a4c7a4b9a1a33031323334a3b5a3b6a3b7a3b8a3b9a1a3 SJIS: k/qWe4zqg2WDTINYg2eCxYK3gUIwMTIzNIJUglWCVoJXgliBQg== diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index f6694668ad768..b2c89aac0f3ae 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -596,7 +596,7 @@ PHP_MINIT_FUNCTION(mysqli) REGISTER_LONG_CONSTANT("MYSQLI_READ_DEFAULT_FILE", MYSQL_READ_DEFAULT_FILE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLI_OPT_CONNECT_TIMEOUT", MYSQL_OPT_CONNECT_TIMEOUT, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLI_OPT_LOCAL_INFILE", MYSQL_OPT_LOCAL_INFILE, CONST_CS | CONST_PERSISTENT); -#if MYSQL_VERSION_ID >= 80021 || defined(MYSQLI_USE_MYSQLND) +#if (MYSQL_VERSION_ID >= 80021 && !defined(MARIADB_BASE_VERSION)) || defined(MYSQLI_USE_MYSQLND) REGISTER_LONG_CONSTANT("MYSQLI_OPT_LOAD_DATA_LOCAL_DIR", MYSQL_OPT_LOAD_DATA_LOCAL_DIR, CONST_CS | CONST_PERSISTENT); #endif REGISTER_LONG_CONSTANT("MYSQLI_INIT_COMMAND", MYSQL_INIT_COMMAND, CONST_CS | CONST_PERSISTENT); @@ -772,6 +772,12 @@ PHP_MINIT_FUNCTION(mysqli) REGISTER_LONG_CONSTANT("MYSQLI_TRANS_COR_RELEASE", TRANS_COR_RELEASE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLI_TRANS_COR_NO_RELEASE", TRANS_COR_NO_RELEASE, CONST_CS | CONST_PERSISTENT); +#ifdef MARIADB_BASE_VERSION + REGISTER_BOOL_CONSTANT("MYSQLI_IS_MARIADB", 1, CONST_CS | CONST_PERSISTENT); +#else + REGISTER_BOOL_CONSTANT("MYSQLI_IS_MARIADB", 0, CONST_CS | CONST_PERSISTENT); +#endif + #ifdef MYSQLI_USE_MYSQLND mysqlnd_reverse_api_register_api(&mysqli_reverse_api); diff --git a/ext/mysqli/mysqli.stub.php b/ext/mysqli/mysqli.stub.php index e0c46a5427bcb..40f82e42e7036 100644 --- a/ext/mysqli/mysqli.stub.php +++ b/ext/mysqli/mysqli.stub.php @@ -4,10 +4,13 @@ final class mysqli_driver { + /** @readonly */ public string $client_info; + /** @readonly */ public int $client_version; + /** @readonly */ public int $driver_version; public bool $reconnect = false; @@ -613,6 +616,8 @@ public function next(): bool {} final class mysqli_sql_exception extends RuntimeException { protected string $sqlstate = "00000"; + + public function getSqlState(): string {} } /** @refcount 1 */ diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 96dee255b2b96..afd86bbe93a40 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -1720,7 +1720,7 @@ static int mysqli_options_get_option_zval_type(int option) #if MYSQL_VERSION_ID > 50605 || defined(MYSQLI_USE_MYSQLND) case MYSQL_SERVER_PUBLIC_KEY: #endif -#if MYSQL_VERSION_ID >= 80021 || defined(MYSQLI_USE_MYSQLND) +#if (MYSQL_VERSION_ID >= 80021 && !defined(MARIADB_BASE_VERSION)) || defined(MYSQLI_USE_MYSQLND) case MYSQL_OPT_LOAD_DATA_LOCAL_DIR: #endif return IS_STRING; diff --git a/ext/mysqli/mysqli_arginfo.h b/ext/mysqli/mysqli_arginfo.h index 4cd285e347f47..c177963d1548f 100644 --- a/ext/mysqli/mysqli_arginfo.h +++ b/ext/mysqli/mysqli_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: e9f4dd04e7d01864c38033bcaf5e03b63e191deb */ + * Stub hash: baf4cb58df96edeb4fc14e4703fe9363cf5ed784 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_affected_rows, 0, 1, MAY_BE_LONG|MAY_BE_STRING) ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0) @@ -720,6 +720,9 @@ ZEND_END_ARG_INFO() #define arginfo_class_mysqli_warning_next arginfo_mysqli_thread_safe +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_mysqli_sql_exception_getSqlState, 0, 0, IS_STRING, 0) +ZEND_END_ARG_INFO() + ZEND_FUNCTION(mysqli_affected_rows); ZEND_FUNCTION(mysqli_autocommit); @@ -842,6 +845,7 @@ ZEND_METHOD(mysqli_result, getIterator); ZEND_METHOD(mysqli_stmt, __construct); ZEND_METHOD(mysqli_warning, __construct); ZEND_METHOD(mysqli_warning, next); +ZEND_METHOD(mysqli_sql_exception, getSqlState); static const zend_function_entry ext_functions[] = { @@ -1083,6 +1087,7 @@ static const zend_function_entry class_mysqli_warning_methods[] = { static const zend_function_entry class_mysqli_sql_exception_methods[] = { + ZEND_ME(mysqli_sql_exception, getSqlState, arginfo_class_mysqli_sql_exception_getSqlState, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/mysqli/mysqli_exception.c b/ext/mysqli/mysqli_exception.c index 3bc80807a7e98..3d15881863e24 100644 --- a/ext/mysqli/mysqli_exception.c +++ b/ext/mysqli/mysqli_exception.c @@ -63,3 +63,17 @@ void php_mysqli_throw_sql_exception(char *sqlstate, int errorno, char *format, . zend_throw_exception_object(&sql_ex); } + +PHP_METHOD(mysqli_sql_exception, getSqlState) +{ + zval *prop; + zval rv; + + ZEND_PARSE_PARAMETERS_NONE(); + + prop = zend_read_property(mysqli_exception_class_entry, Z_OBJ_P(ZEND_THIS), "sqlstate", sizeof("sqlstate")-1, 1, &rv); + ZVAL_DEREF(prop); + zend_string *str = zval_get_string(prop); + + RETURN_STR(str); +} diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c index b905426eeae7e..3fe4408e29dd8 100644 --- a/ext/mysqli/mysqli_nonapi.c +++ b/ext/mysqli/mysqli_nonapi.c @@ -333,7 +333,7 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, bool is_real_connect, b unsigned int allow_local_infile = MyG(allow_local_infile); mysql_options(mysql->mysql, MYSQL_OPT_LOCAL_INFILE, (char *)&allow_local_infile); -#if MYSQL_VERSION_ID >= 80021 || defined(MYSQLI_USE_MYSQLND) +#if (MYSQL_VERSION_ID >= 80021 && !defined(MARIADB_BASE_VERSION)) || defined(MYSQLI_USE_MYSQLND) if (MyG(local_infile_directory) && !php_check_open_basedir(MyG(local_infile_directory))) { mysql_options(mysql->mysql, MYSQL_OPT_LOAD_DATA_LOCAL_DIR, MyG(local_infile_directory)); } diff --git a/ext/mysqli/tests/gh7746.phpt b/ext/mysqli/tests/gh7746.phpt new file mode 100644 index 0000000000000..18fdb03451377 --- /dev/null +++ b/ext/mysqli/tests/gh7746.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #GH-7746 mysqli_sql_exception->sqlstate is inaccessible +--EXTENSIONS-- +mysqli +--SKIPIF-- + +--FILE-- +query("stuff"); +} catch (mysqli_sql_exception $exception) { + var_dump($exception->getSqlState()); +} + +?> +--EXPECT-- +string(5) "42000" diff --git a/ext/mysqli/tests/gh7837.phpt b/ext/mysqli/tests/gh7837.phpt new file mode 100644 index 0000000000000..710d1ef5a4b55 --- /dev/null +++ b/ext/mysqli/tests/gh7837.phpt @@ -0,0 +1,47 @@ +--TEST-- +Bug GH-7837 (large bigints may be truncated) +--EXTENSIONS-- +mysqli +--SKIPIF-- + +--FILE-- +options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true); +$mysql->query("DROP TABLE IF EXISTS test"); +$mysql->query("CREATE TABLE test (`ubigint` bigint unsigned NOT NULL) ENGINE=InnoDB"); +$mysql->query("INSERT INTO test (`ubigint`) VALUES (18446744073709551615)"); +$mysql->query("INSERT INTO test (`ubigint`) VALUES (9223372036854775808)"); +$mysql->query("INSERT INTO test (`ubigint`) VALUES (1)"); +$result = $mysql->query("SELECT ubigint FROM test"); +var_dump($result->fetch_all()); +?> +--CLEAN-- + +--EXPECT-- +array(3) { + [0]=> + array(1) { + [0]=> + string(20) "18446744073709551615" + } + [1]=> + array(1) { + [0]=> + string(19) "9223372036854775808" + } + [2]=> + array(1) { + [0]=> + int(1) + } +} diff --git a/ext/mysqli/tests/mysqli_constants.phpt b/ext/mysqli/tests/mysqli_constants.phpt index 4415f3250cc6d..0380792e06284 100644 --- a/ext/mysqli/tests/mysqli_constants.phpt +++ b/ext/mysqli/tests/mysqli_constants.phpt @@ -47,6 +47,7 @@ $expected_constants = array( "MYSQLI_GROUP_FLAG" => true, "MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED"=> true, "MYSQLI_SERVER_QUERY_NO_INDEX_USED" => true, + "MYSQLI_IS_MARIADB" => true, "MYSQLI_TYPE_DECIMAL" => true, "MYSQLI_TYPE_TINY" => true, @@ -180,7 +181,7 @@ if ($IS_MYSQLND) { $expected_constants["MYSQLI_TYPE_JSON"] = true; } -if ($version > 80021 || $IS_MYSQLND) { +if (($version > 80021 && $constants['mysqli']['MYSQLI_IS_MARIADB']) || $IS_MYSQLND) { $expected_constants['MYSQLI_OPT_LOAD_DATA_LOCAL_DIR'] = true; } diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index 77d0c31aa6dda..885f61446920a 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -1614,9 +1614,9 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_ROW_BUFFER * row_buffer, zval * fiel } else { uint64_t v = #ifndef PHP_WIN32 - (uint64_t) atoll((char *) p); + strtoull((char *) p, NULL, 10); #else - (uint64_t) _atoi64((char *) p); + _strtoui64((char *) p, NULL, 10); #endif bool uns = fields_metadata[i].flags & UNSIGNED_FLAG? TRUE:FALSE; /* We have to make it ASCIIZ temporarily */ diff --git a/ext/oci8/oci8.c b/ext/oci8/oci8.c index 8c71d5746218a..280fba97522ca 100644 --- a/ext/oci8/oci8.c +++ b/ext/oci8/oci8.c @@ -251,24 +251,6 @@ static void php_oci_init_global_handles(void) } /* }}} */ -/* {{{ php_oci_cleanup_global_handles() - * - * Free global handles (if they were initialized before) - */ -static void php_oci_cleanup_global_handles(void) -{ - if (OCI_G(err)) { - PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(err), OCI_HTYPE_ERROR)); - OCI_G(err) = NULL; - } - - if (OCI_G(env)) { - PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(env), OCI_HTYPE_ENV)); - OCI_G(env) = NULL; - } -} -/* }}} */ - /* {{{ PHP_GINIT_FUNCTION * * Zerofill globals during module init @@ -282,10 +264,23 @@ static PHP_GINIT_FUNCTION(oci) /* {{{ PHP_GSHUTDOWN_FUNCTION * * Called for thread shutdown in ZTS, after module shutdown for non-ZTS + * Free global handles (if they were initialized before) */ static PHP_GSHUTDOWN_FUNCTION(oci) { - php_oci_cleanup_global_handles(); + if (oci_globals->err) { + oci_globals->in_call = 1; + OCIHandleFree((dvoid *) oci_globals->err, OCI_HTYPE_ERROR); + oci_globals->in_call = 0; + oci_globals->err = NULL; + } + + if (oci_globals->env) { + oci_globals->in_call = 1; + OCIHandleFree((dvoid *) oci_globals->env, OCI_HTYPE_ENV); + oci_globals->in_call = 0; + oci_globals->env = NULL; + } } /* }}} */ diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 3c892f82a3645..8f6a5aa42b920 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -4086,7 +4086,8 @@ static void preload_remove_empty_includes(void) if (opline->opcode == ZEND_INCLUDE_OR_EVAL && opline->extended_value != ZEND_EVAL && opline->op1_type == IS_CONST && - Z_TYPE_P(RT_CONSTANT(opline, opline->op1)) == IS_STRING) { + Z_TYPE_P(RT_CONSTANT(opline, opline->op1)) == IS_STRING && + opline->result_type == IS_UNUSED) { zend_string *resolved_path = preload_resolve_path(Z_STR_P(RT_CONSTANT(opline, opline->op1))); @@ -4132,7 +4133,7 @@ static void preload_remove_empty_includes(void) if (resolved_path) { zend_persistent_script *incl = zend_hash_find_ptr(preload_scripts, resolved_path); - if (incl && incl->empty) { + if (incl && incl->empty && opline->result_type == IS_UNUSED) { MAKE_NOP(opline); } else { if (!IS_ABSOLUTE_PATH(Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), Z_STRLEN_P(RT_CONSTANT(opline, opline->op1)))) { diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index 824e3cd3575fd..de5ec45de72c8 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -269,6 +269,10 @@ typedef struct _zend_accel_shared_globals { /* uninitialized HashTable Support */ uint32_t uninitialized_bucket[-HT_MIN_MASK]; + /* Tracing JIT */ + void *jit_traces; + const void **jit_exit_groups; + /* Interned Strings Support (must be the last element) */ zend_string_table interned_strings; } zend_accel_shared_globals; diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index f6475c15a5cf0..d3ce786aaca31 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -540,7 +540,7 @@ static uint32_t zend_ssa_cv_info(const zend_op_array *op_array, zend_ssa *ssa, u return info; } -static bool zend_jit_may_avoid_refcounting(const zend_op *opline) +static bool zend_jit_may_avoid_refcounting(const zend_op *opline, uint32_t op1_info) { switch (opline->opcode) { case ZEND_FETCH_OBJ_FUNC_ARG: @@ -552,7 +552,8 @@ static bool zend_jit_may_avoid_refcounting(const zend_op *opline) /* break missing intentionally */ case ZEND_FETCH_OBJ_R: case ZEND_FETCH_OBJ_IS: - if (opline->op2_type == IS_CONST + if ((op1_info & MAY_BE_OBJECT) + && opline->op2_type == IS_CONST && Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_STRING && Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] != '\0') { return 1; @@ -2893,7 +2894,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op } end = ssa->cfg.blocks[b].start + ssa->cfg.blocks[b].len - 1; for (i = ssa->cfg.blocks[b].start; i <= end; i++) { - zend_ssa_op *ssa_op = &ssa->ops[i]; + zend_ssa_op *ssa_op = ssa->ops ? &ssa->ops[i] : NULL; opline = op_array->opcodes + i; switch (opline->opcode) { case ZEND_INIT_FCALL: @@ -2923,7 +2924,10 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op if (opline->result_type != IS_UNUSED) { res_use_info = -1; - if (opline->result_type == IS_CV) { + if (opline->result_type == IS_CV + && ssa->vars + && ssa_op->result_use >= 0 + && !ssa->vars[ssa_op->result_use].no_val) { zend_jit_addr res_use_addr = RES_USE_REG_ADDR(); if (Z_MODE(res_use_addr) != IS_REG @@ -2981,7 +2985,10 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op } else { res_use_info = -1; - if (opline->result_type == IS_CV) { + if (opline->result_type == IS_CV + && ssa->vars + && ssa_op->result_use >= 0 + && !ssa->vars[ssa_op->result_use].no_val) { zend_jit_addr res_use_addr = RES_USE_REG_ADDR(); if (Z_MODE(res_use_addr) != IS_REG @@ -3032,7 +3039,10 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op } else { res_use_info = -1; - if (opline->result_type == IS_CV) { + if (opline->result_type == IS_CV + && ssa->vars + && ssa_op->result_use >= 0 + && !ssa->vars[ssa_op->result_use].no_val) { zend_jit_addr res_use_addr = RES_USE_REG_ADDR(); if (Z_MODE(res_use_addr) != IS_REG @@ -4991,7 +5001,7 @@ ZEND_EXT_API int zend_jit_startup(void *buf, size_t size, bool reattached) #endif } - if (zend_jit_trace_startup() != SUCCESS) { + if (zend_jit_trace_startup(reattached) != SUCCESS) { return FAILURE; } diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 52e9bbb9eede0..9c94a3a0b740c 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -11139,7 +11139,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst, && (res_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) && (ssa_op+1)->op1_use == ssa_op->result_def && !(op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF) - (MAY_BE_STRING|MAY_BE_LONG))) - && zend_jit_may_avoid_refcounting(opline+1)) { + && zend_jit_may_avoid_refcounting(opline+1, res_info)) { result_avoid_refcounting = 1; ssa->var_info[ssa_op->result_def].avoid_refcounting = 1; } @@ -11276,28 +11276,28 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst, |6: } - if ((opline->opcode != ZEND_FETCH_DIM_IS && (op1_info & MAY_BE_UNDEF)) || (op2_info & MAY_BE_UNDEF)) { - | SET_EX_OPLINE opline, REG0 - if (opline->opcode != ZEND_FETCH_DIM_IS && (op1_info & MAY_BE_UNDEF)) { - may_throw = 1; - | IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >1, ZREG_TMP1 - | // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var)))); - | LOAD_32BIT_VAL FCARG1w, opline->op1.var - | EXT_CALL zend_jit_undefined_op_helper, REG0 - |1: - } + if ((op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_ARRAY|MAY_BE_OBJECT|may_be_string))) + && (!exit_addr || !(op1_info & (MAY_BE_ARRAY|MAY_BE_OBJECT|may_be_string)))) { + if ((opline->opcode != ZEND_FETCH_DIM_IS && (op1_info & MAY_BE_UNDEF)) || (op2_info & MAY_BE_UNDEF)) { + | SET_EX_OPLINE opline, REG0 + if (opline->opcode != ZEND_FETCH_DIM_IS && (op1_info & MAY_BE_UNDEF)) { + may_throw = 1; + | IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >1, ZREG_TMP1 + | // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var)))); + | LOAD_32BIT_VAL FCARG1w, opline->op1.var + | EXT_CALL zend_jit_undefined_op_helper, REG0 + |1: + } - if (op2_info & MAY_BE_UNDEF) { - may_throw = 1; - | IF_NOT_ZVAL_TYPE op2_addr, IS_UNDEF, >1, ZREG_TMP1 - | LOAD_32BIT_VAL FCARG1w, opline->op2.var - | EXT_CALL zend_jit_undefined_op_helper, REG0 - |1: + if (op2_info & MAY_BE_UNDEF) { + may_throw = 1; + | IF_NOT_ZVAL_TYPE op2_addr, IS_UNDEF, >1, ZREG_TMP1 + | LOAD_32BIT_VAL FCARG1w, opline->op2.var + | EXT_CALL zend_jit_undefined_op_helper, REG0 + |1: + } } - } - if ((op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_ARRAY|MAY_BE_OBJECT|may_be_string))) - && (!exit_addr || !(op1_info & (MAY_BE_ARRAY|MAY_BE_OBJECT|may_be_string)))) { if (opline->opcode != ZEND_FETCH_DIM_IS && opline->opcode != ZEND_FETCH_LIST_R) { may_throw = 1; if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) { @@ -12419,7 +12419,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst, && !(flags & ZEND_JIT_EXIT_FREE_OP1) && (res_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) && (ssa_op+1)->op1_use == ssa_op->result_def - && zend_jit_may_avoid_refcounting(opline+1)) { + && zend_jit_may_avoid_refcounting(opline+1, res_info)) { result_avoid_refcounting = 1; ssa->var_info[ssa_op->result_def].avoid_refcounting = 1; } diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 590df08784794..9a905c4c0175f 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -377,6 +377,8 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_r_helper(zend_array *ht, zval *dim, zend_ulong hval; zend_string *offset_key; zval *retval; + zend_execute_data *execute_data; + const zend_op *opline; if (Z_TYPE_P(dim) == IS_REFERENCE) { dim = Z_REFVAL_P(dim); @@ -390,16 +392,91 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_r_helper(zend_array *ht, zval *dim, offset_key = Z_STR_P(dim); goto str_index; case IS_UNDEF: + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + execute_data = EG(current_execute_data); + opline = EX(opline); zend_jit_undefined_op_helper(EG(current_execute_data)->opline->op2.var); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + return; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return; + } ZEND_FALLTHROUGH; case IS_NULL: offset_key = ZSTR_EMPTY_ALLOC(); goto str_index; case IS_DOUBLE: - hval = zend_dval_to_lval_safe(Z_DVAL_P(dim)); + hval = zend_dval_to_lval(Z_DVAL_P(dim)); + if (!zend_is_long_compatible(Z_DVAL_P(dim), hval)) { + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + execute_data = EG(current_execute_data); + opline = EX(opline); + zend_incompatible_double_to_long_error(Z_DVAL_P(dim)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + return; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return; + } + } goto num_index; case IS_RESOURCE: + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + execute_data = EG(current_execute_data); + opline = EX(opline); zend_use_resource_as_offset(dim); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + return; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return; + } hval = Z_RES_HANDLE_P(dim); goto num_index; case IS_FALSE: @@ -442,6 +519,8 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_is_helper(zend_array *ht, zval *dim zend_ulong hval; zend_string *offset_key; zval *retval; + zend_execute_data *execute_data; + const zend_op *opline; if (Z_TYPE_P(dim) == IS_REFERENCE) { dim = Z_REFVAL_P(dim); @@ -455,16 +534,91 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_is_helper(zend_array *ht, zval *dim offset_key = Z_STR_P(dim); goto str_index; case IS_UNDEF: + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + execute_data = EG(current_execute_data); + opline = EX(opline); zend_jit_undefined_op_helper(EG(current_execute_data)->opline->op2.var); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + return; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return; + } ZEND_FALLTHROUGH; case IS_NULL: offset_key = ZSTR_EMPTY_ALLOC(); goto str_index; case IS_DOUBLE: - hval = zend_dval_to_lval_safe(Z_DVAL_P(dim)); + hval = zend_dval_to_lval(Z_DVAL_P(dim)); + if (!zend_is_long_compatible(Z_DVAL_P(dim), hval)) { + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + execute_data = EG(current_execute_data); + opline = EX(opline); + zend_incompatible_double_to_long_error(Z_DVAL_P(dim)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + return; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return; + } + } goto num_index; case IS_RESOURCE: + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + execute_data = EG(current_execute_data); + opline = EX(opline); zend_use_resource_as_offset(dim); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + return; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return; + } hval = Z_RES_HANDLE_P(dim); goto num_index; case IS_FALSE: @@ -518,16 +672,55 @@ static int ZEND_FASTCALL zend_jit_fetch_dim_isset_helper(zend_array *ht, zval *d offset_key = Z_STR_P(dim); goto str_index; case IS_UNDEF: + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } zend_jit_undefined_op_helper(EG(current_execute_data)->opline->op2.var); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + return 0; + } + if (EG(exception)) { + return 0; + } ZEND_FALLTHROUGH; case IS_NULL: offset_key = ZSTR_EMPTY_ALLOC(); goto str_index; case IS_DOUBLE: - hval = zend_dval_to_lval_safe(Z_DVAL_P(dim)); + hval = zend_dval_to_lval(Z_DVAL_P(dim)); + if (!zend_is_long_compatible(Z_DVAL_P(dim), hval)) { + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + zend_incompatible_double_to_long_error(Z_DVAL_P(dim)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + return 0; + } + if (EG(exception)) { + return 0; + } + } goto num_index; case IS_RESOURCE: + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } zend_use_resource_as_offset(dim); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + return 0; + } + if (EG(exception)) { + return 0; + } hval = Z_RES_HANDLE_P(dim); goto num_index; case IS_FALSE: @@ -587,6 +780,9 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_rw_helper(zend_array *ht, zval *di case IS_UNDEF: execute_data = EG(current_execute_data); opline = EX(opline); + if (UNEXPECTED(opline->opcode == ZEND_HANDLE_EXCEPTION)) { + opline = EG(opline_before_exception); + } if (!zend_jit_undefined_op_helper_write(ht, opline->op2.var)) { if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { if (EG(exception)) { @@ -727,10 +923,61 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_w_helper(zend_array *ht, zval *dim offset_key = ZSTR_EMPTY_ALLOC(); goto str_index; case IS_DOUBLE: - hval = zend_dval_to_lval_safe(Z_DVAL_P(dim)); + hval = zend_dval_to_lval(Z_DVAL_P(dim)); + if (!zend_is_long_compatible(Z_DVAL_P(dim), hval)) { + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + execute_data = EG(current_execute_data); + opline = EX(opline); + zend_incompatible_double_to_long_error(Z_DVAL_P(dim)); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + return NULL; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return NULL; + } + } goto num_index; case IS_RESOURCE: + /* The array may be destroyed while throwing the notice. + * Temporarily increase the refcount to detect this situation. */ + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(ht); + } + execute_data = EG(current_execute_data); + opline = EX(opline); zend_use_resource_as_offset(dim); + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { + zend_array_destroy(ht); + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + if (EG(exception)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } else { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + return NULL; + } + if (EG(exception)) { + if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + return NULL; + } hval = Z_RES_HANDLE_P(dim); goto num_index; case IS_FALSE: @@ -833,7 +1080,15 @@ static zend_string* ZEND_FASTCALL zend_jit_fetch_dim_str_r_helper(zend_string *s zend_long offset; if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) { + if (!(GC_FLAGS(str) & IS_STR_INTERNED)) { + GC_ADDREF(str); + } offset = zend_check_string_offset(dim/*, BP_VAR_R*/); + if (!(GC_FLAGS(str) & IS_STR_INTERNED) && UNEXPECTED(GC_DELREF(str) == 0)) { + zend_string *ret = zend_jit_fetch_dim_str_offset(str, offset); + zend_string_efree(str); + return ret; + } } else { offset = Z_LVAL_P(dim); } @@ -893,13 +1148,15 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_str_is_helper(zend_string *str, zva static void ZEND_FASTCALL zend_jit_fetch_dim_obj_r_helper(zval *container, zval *dim, zval *result) { zval *retval; + zend_object *obj = Z_OBJ_P(container); + GC_ADDREF(obj); if (UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) { zend_jit_undefined_op_helper(EG(current_execute_data)->opline->op2.var); dim = &EG(uninitialized_zval); } - retval = Z_OBJ_HT_P(container)->read_dimension(Z_OBJ_P(container), dim, BP_VAR_R, result); + retval = obj->handlers->read_dimension(obj, dim, BP_VAR_R, result); if (retval) { if (result != retval) { @@ -910,18 +1167,23 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_obj_r_helper(zval *container, zval } else { ZVAL_NULL(result); } + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } static void ZEND_FASTCALL zend_jit_fetch_dim_obj_is_helper(zval *container, zval *dim, zval *result) { zval *retval; + zend_object *obj = Z_OBJ_P(container); + GC_ADDREF(obj); if (UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) { zend_jit_undefined_op_helper(EG(current_execute_data)->opline->op2.var); dim = &EG(uninitialized_zval); } - retval = Z_OBJ_HT_P(container)->read_dimension(Z_OBJ_P(container), dim, BP_VAR_IS, result); + retval = obj->handlers->read_dimension(obj, dim, BP_VAR_IS, result); if (retval) { if (result != retval) { @@ -932,6 +1194,9 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_obj_is_helper(zval *container, zval } else { ZVAL_NULL(result); } + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value, zval *result) @@ -1090,9 +1355,18 @@ static zend_always_inline void ZEND_FASTCALL zend_jit_fetch_dim_obj_helper(zval zval *retval; if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - retval = Z_OBJ_HT_P(object_ptr)->read_dimension(Z_OBJ_P(object_ptr), dim, type, result); + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + if (dim && UNEXPECTED(Z_ISUNDEF_P(dim))) { + const zend_op *opline = EG(current_execute_data)->opline; + zend_jit_undefined_op_helper(opline->op2.var); + dim = &EG(uninitialized_zval); + } + + retval = obj->handlers->read_dimension(obj, dim, type, result); if (UNEXPECTED(retval == &EG(uninitialized_zval))) { - zend_class_entry *ce = Z_OBJCE_P(object_ptr); + zend_class_entry *ce = obj->ce; ZVAL_NULL(result); zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name)); @@ -1103,7 +1377,7 @@ static zend_always_inline void ZEND_FASTCALL zend_jit_fetch_dim_obj_helper(zval retval = result; } if (Z_TYPE_P(retval) != IS_OBJECT) { - zend_class_entry *ce = Z_OBJCE_P(object_ptr); + zend_class_entry *ce = obj->ce; zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name)); } } else if (UNEXPECTED(Z_REFCOUNT_P(retval) == 1)) { @@ -1116,6 +1390,9 @@ static zend_always_inline void ZEND_FASTCALL zend_jit_fetch_dim_obj_helper(zval ZEND_ASSERT(EG(exception) && "read_dimension() returned NULL without exception"); ZVAL_UNDEF(result); } + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (!dim) { zend_throw_error(NULL, "[] operator not supported for strings"); @@ -1127,9 +1404,15 @@ static zend_always_inline void ZEND_FASTCALL zend_jit_fetch_dim_obj_helper(zval } ZVAL_UNDEF(result); } else if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); zend_array *arr = zend_new_array(0); ZVAL_ARR(object_ptr, arr); + GC_ADDREF(arr); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(arr) == 0)) { + zend_array_destroy(arr); + ZVAL_NULL(result); + return; + } zval *var; if (dim) { if (type == BP_VAR_W) { @@ -1174,17 +1457,42 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_obj_rw_helper(zval *object_ptr, zva static void ZEND_FASTCALL zend_jit_assign_dim_helper(zval *object_ptr, zval *dim, zval *value, zval *result) { - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && EXPECTED(dim != NULL)) { + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_object *obj = Z_OBJ_P(object_ptr); + + GC_ADDREF(obj); + if (dim && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) { + const zend_op *opline = EG(current_execute_data)->opline; + zend_jit_undefined_op_helper(opline->op2.var); + dim = &EG(uninitialized_zval); + } + + if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { + const zend_op *op_data = EG(current_execute_data)->opline + 1; + ZEND_ASSERT(op_data->opcode == ZEND_OP_DATA && op_data->op1_type == IS_CV); + zend_jit_undefined_op_helper(op_data->op1.var); + value = &EG(uninitialized_zval); + } else { + ZVAL_DEREF(value); + } + + obj->handlers->write_dimension(obj, dim, value); + if (result) { + if (EXPECTED(!EG(exception))) { + ZVAL_COPY(result, value); + } else { + ZVAL_UNDEF(result); + } + } + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); + } + return; + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) && EXPECTED(dim != NULL)) { zend_assign_to_string_offset(object_ptr, dim, value, result); return; } - if (dim && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) { - const zend_op *opline = EG(current_execute_data)->opline; - zend_jit_undefined_op_helper(opline->op2.var); - dim = &EG(uninitialized_zval); - } - if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { const zend_op *op_data = EG(current_execute_data)->opline + 1; ZEND_ASSERT(op_data->opcode == ZEND_OP_DATA && op_data->op1_type == IS_CV); @@ -1192,25 +1500,23 @@ static void ZEND_FASTCALL zend_jit_assign_dim_helper(zval *object_ptr, zval *dim value = &EG(uninitialized_zval); } - if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { - ZVAL_DEREF(value); - Z_OBJ_HT_P(object_ptr)->write_dimension(Z_OBJ_P(object_ptr), dim, value); - if (result) { - if (EXPECTED(!EG(exception))) { - ZVAL_COPY(result, value); - } else { - ZVAL_UNDEF(result); - } - } - } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { zend_throw_error(NULL, "[] operator not supported for strings"); if (result) { ZVAL_UNDEF(result); } } else if (Z_TYPE_P(object_ptr) == IS_FALSE) { - zend_false_to_array_deprecated(); zend_array *arr = zend_new_array(0); ZVAL_ARR(object_ptr, arr); + GC_ADDREF(arr); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(arr) == 0)) { + zend_array_destroy(arr); + if (result) { + ZVAL_NULL(result); + } + return; + } zval *var = dim ? zend_jit_fetch_dim_w_helper(arr, dim) : zend_hash_next_index_insert_new(arr, &EG(uninitialized_zval)); @@ -1226,6 +1532,11 @@ static void ZEND_FASTCALL zend_jit_assign_dim_helper(zval *object_ptr, zval *dim ZVAL_COPY(result, var); } } else { + if (dim && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) { + const zend_op *opline = EG(current_execute_data)->opline; + zend_jit_undefined_op_helper(opline->op2.var); + dim = &EG(uninitialized_zval); + } zend_throw_error(NULL, "Cannot use a scalar value as an array"); if (result) { ZVAL_UNDEF(result); @@ -1236,16 +1547,22 @@ static void ZEND_FASTCALL zend_jit_assign_dim_helper(zval *object_ptr, zval *dim static void ZEND_FASTCALL zend_jit_assign_dim_op_helper(zval *container, zval *dim, zval *value, binary_op_type binary_op) { if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { - zval *object = container; - zval *property = dim; + zend_object *obj = Z_OBJ_P(container); zval *z; zval rv, res; - z = Z_OBJ_HT_P(object)->read_dimension(Z_OBJ_P(object), property, BP_VAR_R, &rv); + GC_ADDREF(obj); + if (dim && UNEXPECTED(Z_ISUNDEF_P(dim))) { + const zend_op *opline = EG(current_execute_data)->opline; + zend_jit_undefined_op_helper(opline->op2.var); + dim = &EG(uninitialized_zval); + } + + z = obj->handlers->read_dimension(obj, dim, BP_VAR_R, &rv); if (z != NULL) { if (binary_op(&res, Z_ISREF_P(z) ? Z_REFVAL_P(z) : z, value) == SUCCESS) { - Z_OBJ_HT_P(object)->write_dimension(Z_OBJ_P(object), property, &res); + obj->handlers->write_dimension(obj, dim, &res); } if (z == &rv) { zval_ptr_dtor(&rv); @@ -1254,6 +1571,12 @@ static void ZEND_FASTCALL zend_jit_assign_dim_op_helper(zval *container, zval *d } else { zend_error(E_WARNING, "Attempt to assign property of non-object"); } + if (UNEXPECTED(GC_DELREF(obj) == 0)) { + zend_objects_store_del(obj); +//??? if (retval) { +//??? ZVAL_NULL(retval); +//??? } + } } else if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) { if (!dim) { zend_throw_error(NULL, "[] operator not supported for strings"); @@ -1264,9 +1587,14 @@ static void ZEND_FASTCALL zend_jit_assign_dim_op_helper(zval *container, zval *d zend_wrong_string_offset_error(); } } else if (Z_TYPE_P(container) == IS_FALSE) { - zend_false_to_array_deprecated(); zend_array *arr = zend_new_array(0); ZVAL_ARR(container, arr); + GC_ADDREF(arr); + zend_false_to_array_deprecated(); + if (UNEXPECTED(GC_DELREF(arr) == 0)) { + zend_array_destroy(arr); + return; + } zval *var = dim ? zend_jit_fetch_dim_rw_helper(arr, dim) : zend_hash_next_index_insert_new(arr, &EG(uninitialized_zval)); diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 1167dba8f2b79..b2afc7ff4dd9f 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -46,20 +46,33 @@ static zend_always_inline const char *zend_jit_trace_star_desc(uint8_t trace_fla } } -static int zend_jit_trace_startup(void) +static int zend_jit_trace_startup(zend_bool reattached) { - zend_jit_traces = (zend_jit_trace_info*)zend_shared_alloc(sizeof(zend_jit_trace_info) * JIT_G(max_root_traces)); - if (!zend_jit_traces) { - return FAILURE; - } - zend_jit_exit_groups = (const void**)zend_shared_alloc(sizeof(void*) * (ZEND_JIT_TRACE_MAX_EXITS/ZEND_JIT_EXIT_POINTS_PER_GROUP)); - if (!zend_jit_exit_groups) { - return FAILURE; + if (!reattached) { + zend_jit_traces = (zend_jit_trace_info*)zend_shared_alloc(sizeof(zend_jit_trace_info) * JIT_G(max_root_traces)); + if (!zend_jit_traces) { + return FAILURE; + } + zend_jit_exit_groups = (const void**)zend_shared_alloc(sizeof(void*) * (ZEND_JIT_TRACE_MAX_EXITS/ZEND_JIT_EXIT_POINTS_PER_GROUP)); + if (!zend_jit_exit_groups) { + return FAILURE; + } + ZEND_JIT_TRACE_NUM = 1; + ZEND_JIT_COUNTER_NUM = 0; + ZEND_JIT_EXIT_NUM = 0; + ZEND_JIT_EXIT_COUNTERS = 0; + ZCSG(jit_traces) = zend_jit_traces; + ZCSG(jit_exit_groups) = zend_jit_exit_groups; + } else { + zend_jit_traces = ZCSG(jit_traces); + if (!zend_jit_traces) { + return FAILURE; + } + zend_jit_exit_groups = ZCSG(jit_exit_groups); + if (!zend_jit_exit_groups) { + return FAILURE; + } } - ZEND_JIT_TRACE_NUM = 1; - ZEND_JIT_COUNTER_NUM = 0; - ZEND_JIT_EXIT_NUM = 0; - ZEND_JIT_EXIT_COUNTERS = 0; memset(&dummy_op_array, 0, sizeof(dummy_op_array)); dummy_op_array.fn_flags = ZEND_ACC_DONE_PASS_TWO; @@ -4839,15 +4852,13 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par op2_info = OP2_INFO(); CHECK_OP2_TRACE_TYPE(); op1_info = OP1_INFO(); - if (ssa->vars[ssa_op->op1_use].no_val) { - if ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) == MAY_BE_LONG - || (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) == MAY_BE_DOUBLE) { - if (STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var)) != IS_LONG - && STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var)) != IS_DOUBLE) { - /* type may be not set */ - op1_info |= MAY_BE_NULL; - } - } + if ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) == MAY_BE_LONG + || (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_GUARD)) == MAY_BE_DOUBLE) { + if (STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var)) != IS_LONG + && STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var)) != IS_DOUBLE) { + /* type may be not set */ + op1_info |= MAY_BE_NULL; + } } op1_def_info = OP1_DEF_INFO(); if (op1_type != IS_UNKNOWN && (op1_info & MAY_BE_GUARD)) { diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 937b36b5cc00e..a0fc024b21c7f 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -763,17 +763,12 @@ static size_t tsrm_tls_offset; || } |.endmacro -|.macro LONG_OP, long_ins, reg, addr +|.macro LONG_OP, long_ins, reg, addr, tmp_reg || if (Z_MODE(addr) == IS_CONST_ZVAL) { | .if X64 || if (!IS_SIGNED_32BIT(Z_LVAL_P(Z_ZV(addr)))) { -|| if (reg != ZREG_R0) { -| mov64 r0, Z_LVAL_P(Z_ZV(addr)) -| long_ins Ra(reg), r0 -|| } else { -| mov64 r1, Z_LVAL_P(Z_ZV(addr)) -| long_ins Ra(reg), r1 -|| } +| mov64 tmp_reg, Z_LVAL_P(Z_ZV(addr)) +| long_ins Ra(reg), tmp_reg || } else { | long_ins Ra(reg), Z_LVAL_P(Z_ZV(addr)) || } @@ -853,25 +848,25 @@ static size_t tsrm_tls_offset; || } |.endmacro -|.macro LONG_MATH, opcode, reg, addr +|.macro LONG_MATH, opcode, reg, addr, tmp_reg || switch (opcode) { || case ZEND_ADD: -| LONG_OP add, reg, addr +| LONG_OP add, reg, addr, Ra(tmp_reg) || break; || case ZEND_SUB: -| LONG_OP sub, reg, addr +| LONG_OP sub, reg, addr, Ra(tmp_reg) || break; || case ZEND_MUL: -| LONG_OP imul, reg, addr +| LONG_OP imul, reg, addr, Ra(tmp_reg) || break; || case ZEND_BW_OR: -| LONG_OP or, reg, addr +| LONG_OP or, reg, addr, Ra(tmp_reg) || break; || case ZEND_BW_AND: -| LONG_OP and, reg, addr +| LONG_OP and, reg, addr, Ra(tmp_reg) || break; || case ZEND_BW_XOR: -| LONG_OP xor, reg, addr +| LONG_OP xor, reg, addr, Ra(tmp_reg) || break; || default: || ZEND_UNREACHABLE(); @@ -3458,7 +3453,7 @@ static int zend_jit_trace_link_to_root(dasm_State **Dst, zend_jit_trace_info *t, #if defined(__x86_64__) || defined(_M_X64) prologue_size = 17; #else - prologue_size = 12; + prologue_size = 13; #endif } link_addr = (const void*)((const char*)t->code_start + prologue_size); @@ -4423,7 +4418,17 @@ static int zend_jit_math_long_long(dasm_State **Dst, } else if (same_ops && opcode != ZEND_DIV) { | LONG_MATH_REG opcode, Ra(result_reg), Ra(result_reg) } else { - | LONG_MATH opcode, result_reg, op2_addr + zend_reg tmp_reg; + + if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_R0) { + tmp_reg = ZREG_R1; + } else if (result_reg != ZREG_R0) { + tmp_reg = ZREG_R0; + } else { + tmp_reg = ZREG_R1; + } + | LONG_MATH opcode, result_reg, op2_addr, tmp_reg + (void)tmp_reg; } } if (may_overflow) { @@ -5057,9 +5062,6 @@ static int zend_jit_long_math_helper(dasm_State **Dst, if (opcode == ZEND_MOD) { result_reg = ZREG_RAX; - if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RAX) { - | mov aword T1, r0 // save - } } else if (Z_MODE(res_addr) == IS_REG) { if ((opline->opcode == ZEND_SL || opline->opcode == ZEND_SR) && opline->op2_type != IS_CONST) { @@ -5177,13 +5179,27 @@ static int zend_jit_long_math_helper(dasm_State **Dst, } else if (zend_long_is_power_of_two(op2_lval) && op1_range && op1_range->min >= 0) { zval tmp; zend_jit_addr tmp_addr; + zend_reg tmp_reg; /* Optimisation for mod of power of 2 */ ZVAL_LONG(&tmp, op2_lval - 1); tmp_addr = ZEND_ADDR_CONST_ZVAL(&tmp); + if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_R0) { + tmp_reg = ZREG_R1; + } else if (result_reg != ZREG_R0) { + tmp_reg = ZREG_R0; + } else { + tmp_reg = ZREG_R1; + } | GET_ZVAL_LVAL result_reg, op1_addr - | LONG_MATH ZEND_BW_AND, result_reg, tmp_addr + | LONG_MATH ZEND_BW_AND, result_reg, tmp_addr, tmp_reg + (void)tmp_reg; } else { + if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RAX) { + | mov aword T1, r0 // save + } else if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RCX) { + | mov aword T1, Ra(ZREG_RCX) // save + } result_reg = ZREG_RDX; if (op2_lval == -1) { | xor Ra(result_reg), Ra(result_reg) @@ -5199,6 +5215,8 @@ static int zend_jit_long_math_helper(dasm_State **Dst, } if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RAX) { | mov r0, aword T1 // restore + } else if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RCX) { + | mov Ra(ZREG_RCX), aword T1 // restore } } } else { @@ -5240,6 +5258,9 @@ static int zend_jit_long_math_helper(dasm_State **Dst, |.code } + if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RAX) { + | mov aword T1, r0 // save + } result_reg = ZREG_RDX; | GET_ZVAL_LVAL ZREG_RAX, op1_addr |.if X64 @@ -5260,8 +5281,18 @@ static int zend_jit_long_math_helper(dasm_State **Dst, | GET_ZVAL_LVAL result_reg, op1_addr | LONG_MATH_REG opcode, Ra(result_reg), Ra(result_reg) } else { + zend_reg tmp_reg; + + if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_R0) { + tmp_reg = ZREG_R1; + } else if (result_reg != ZREG_R0) { + tmp_reg = ZREG_R0; + } else { + tmp_reg = ZREG_R1; + } | GET_ZVAL_LVAL result_reg, op1_addr - | LONG_MATH opcode, result_reg, op2_addr + | LONG_MATH opcode, result_reg, op2_addr, tmp_reg + (void)tmp_reg; } if (Z_MODE(res_addr) != IS_REG || Z_REG(res_addr) != result_reg) { @@ -7040,13 +7071,13 @@ static int zend_jit_cmp_long_long(dasm_State **Dst, if (Z_MODE(op2_addr) == IS_CONST_ZVAL && Z_LVAL_P(Z_ZV(op2_addr)) == 0) { | test Ra(Z_REG(op1_addr)), Ra(Z_REG(op1_addr)) } else { - | LONG_OP cmp, Z_REG(op1_addr), op2_addr + | LONG_OP cmp, Z_REG(op1_addr), op2_addr, r0 } } else if (Z_MODE(op2_addr) == IS_REG) { if (Z_MODE(op1_addr) == IS_CONST_ZVAL && Z_LVAL_P(Z_ZV(op1_addr)) == 0) { | test Ra(Z_REG(op2_addr)), Ra(Z_REG(op2_addr)) } else { - | LONG_OP cmp, Z_REG(op2_addr), op1_addr + | LONG_OP cmp, Z_REG(op2_addr), op1_addr, r0 } swap = 1; } else if (Z_MODE(op1_addr) == IS_CONST_ZVAL && Z_MODE(op2_addr) != IS_CONST_ZVAL) { @@ -7059,7 +7090,7 @@ static int zend_jit_cmp_long_long(dasm_State **Dst, if (Z_MODE(op2_addr) == IS_CONST_ZVAL && Z_LVAL_P(Z_ZV(op2_addr)) == 0) { | test r0, r0 } else { - | LONG_OP cmp, ZREG_R0, op2_addr + | LONG_OP cmp, ZREG_R0, op2_addr, r0 } } @@ -11788,7 +11819,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst, && (res_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) && (ssa_op+1)->op1_use == ssa_op->result_def && !(op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF) - (MAY_BE_STRING|MAY_BE_LONG))) - && zend_jit_may_avoid_refcounting(opline+1)) { + && zend_jit_may_avoid_refcounting(opline+1, res_info)) { result_avoid_refcounting = 1; ssa->var_info[ssa_op->result_def].avoid_refcounting = 1; } @@ -11941,28 +11972,28 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst, |6: } - if ((opline->opcode != ZEND_FETCH_DIM_IS && (op1_info & MAY_BE_UNDEF)) || (op2_info & MAY_BE_UNDEF)) { - | SET_EX_OPLINE opline, r0 - if (opline->opcode != ZEND_FETCH_DIM_IS && (op1_info & MAY_BE_UNDEF)) { - may_throw = 1; - | IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >1 - | // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var)))); - | mov FCARG1d, opline->op1.var - | EXT_CALL zend_jit_undefined_op_helper, r0 - |1: - } + if ((op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_ARRAY|MAY_BE_OBJECT|may_be_string))) + && (!exit_addr || !(op1_info & (MAY_BE_ARRAY|MAY_BE_OBJECT|may_be_string)))) { + if ((opline->opcode != ZEND_FETCH_DIM_IS && (op1_info & MAY_BE_UNDEF)) || (op2_info & MAY_BE_UNDEF)) { + | SET_EX_OPLINE opline, r0 + if (opline->opcode != ZEND_FETCH_DIM_IS && (op1_info & MAY_BE_UNDEF)) { + may_throw = 1; + | IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >1 + | // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var)))); + | mov FCARG1d, opline->op1.var + | EXT_CALL zend_jit_undefined_op_helper, r0 + |1: + } - if (op2_info & MAY_BE_UNDEF) { - may_throw = 1; - | IF_NOT_ZVAL_TYPE op2_addr, IS_UNDEF, >1 - | mov FCARG1d, opline->op2.var - | EXT_CALL zend_jit_undefined_op_helper, r0 - |1: + if (op2_info & MAY_BE_UNDEF) { + may_throw = 1; + | IF_NOT_ZVAL_TYPE op2_addr, IS_UNDEF, >1 + | mov FCARG1d, opline->op2.var + | EXT_CALL zend_jit_undefined_op_helper, r0 + |1: + } } - } - if ((op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_ARRAY|MAY_BE_OBJECT|may_be_string))) - && (!exit_addr || !(op1_info & (MAY_BE_ARRAY|MAY_BE_OBJECT|may_be_string)))) { if (opline->opcode != ZEND_FETCH_DIM_IS && opline->opcode != ZEND_FETCH_LIST_R) { may_throw = 1; if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) { @@ -13120,7 +13151,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst, && !(flags & ZEND_JIT_EXIT_FREE_OP1) && (res_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) && (ssa_op+1)->op1_use == ssa_op->result_def - && zend_jit_may_avoid_refcounting(opline+1)) { + && zend_jit_may_avoid_refcounting(opline+1, res_info)) { result_avoid_refcounting = 1; ssa->var_info[ssa_op->result_def].avoid_refcounting = 1; } diff --git a/ext/opcache/tests/jit/add_012.phpt b/ext/opcache/tests/jit/add_012.phpt new file mode 100644 index 0000000000000..645f8f4bdd9b5 --- /dev/null +++ b/ext/opcache/tests/jit/add_012.phpt @@ -0,0 +1,19 @@ +--TEST-- +JIT ADD: 012 register allocation for 64-bit constant +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--SKIPIF-- + +--FILE-- + +DONE +--EXPECT-- +DONE \ No newline at end of file diff --git a/ext/opcache/tests/jit/assign_048.phpt b/ext/opcache/tests/jit/assign_048.phpt new file mode 100644 index 0000000000000..a6bcf14933a78 --- /dev/null +++ b/ext/opcache/tests/jit/assign_048.phpt @@ -0,0 +1,43 @@ +--TEST-- +JIT ASSIGN: incorrect type store elimination +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +opcache.protect_memory=1 +opcache.optimization_level=0x7FFEBFFF +--FILE-- + +DONE +--EXPECTF-- +Warning: Undefined variable $a in %sassign_048.php on line 7 + +Warning: Undefined variable $a in %sassign_048.php on line 7 + +Warning: Undefined variable $a in %sassign_048.php on line 7 + +Warning: Undefined variable $a in %sassign_048.php on line 7 + +Warning: Undefined variable $a in %sassign_048.php on line 7 + +Warning: Undefined variable $a in %sassign_048.php on line 7 + +Warning: Undefined variable $a in %sassign_048.php on line 7 + +Warning: Undefined variable $a in %sassign_048.php on line 7 + +Warning: Undefined variable $a in %sassign_048.php on line 7 + +Warning: Undefined variable $a in %sassign_048.php on line 7 +DONE diff --git a/ext/opcache/tests/jit/assign_dim_op_005.phpt b/ext/opcache/tests/jit/assign_dim_op_005.phpt new file mode 100644 index 0000000000000..62af633eb3122 --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_op_005.phpt @@ -0,0 +1,32 @@ +--TEST-- +JIT ASSIGN_DIM_OP: Undefined variable and index with exception +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +getMessage(), "\n"; +} +try { + test2(); +} catch (Exception $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +Undefined variable $undef +Undefined variable $a diff --git a/ext/opcache/tests/jit/assign_dim_op_006.phpt b/ext/opcache/tests/jit/assign_dim_op_006.phpt new file mode 100644 index 0000000000000..075a6c34e95d9 --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_op_006.phpt @@ -0,0 +1,19 @@ +--TEST-- +JIT ASSIGN_DIM_OP 006: Cloberring array be user error handler +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- + +--EXPECT-- +int(0) diff --git a/ext/opcache/tests/jit/assign_op_008.phpt b/ext/opcache/tests/jit/assign_op_008.phpt new file mode 100644 index 0000000000000..efd9418741fc0 --- /dev/null +++ b/ext/opcache/tests/jit/assign_op_008.phpt @@ -0,0 +1,22 @@ +--TEST-- +JIT ASSIGN_OP: 008 Arrays merging with itself +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- + +DONE +--EXPECTF-- +Warning: Undefined array key "b" in %sassign_op_008.php on line 6 +DONE diff --git a/ext/opcache/tests/jit/cmp_008.phpt b/ext/opcache/tests/jit/cmp_008.phpt new file mode 100644 index 0000000000000..6216de5527726 --- /dev/null +++ b/ext/opcache/tests/jit/cmp_008.phpt @@ -0,0 +1,26 @@ +--TEST-- +JIT CMP: 008 Wrong range inference for comparison between IS_LONG and IS_FALSE/IS_TRUE +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +opcache.protect_memory=1 +--FILE-- + +--EXPECTF-- +Warning: Undefined variable $a in %scmp_008.php on line 3 + +Warning: Undefined variable $a in %scmp_008.php on line 3 + +Fatal error: Uncaught DivisionByZeroError: Modulo by zero in %scmp_008.php:3 +Stack trace: +#0 %scmp_008.php(6): test() +#1 {main} + thrown in %scmp_008.php on line 3 diff --git a/ext/opcache/tests/jit/fetch_dim_r_010.phpt b/ext/opcache/tests/jit/fetch_dim_r_010.phpt new file mode 100644 index 0000000000000..677f4a411b6aa --- /dev/null +++ b/ext/opcache/tests/jit/fetch_dim_r_010.phpt @@ -0,0 +1,18 @@ +--TEST-- +JIT FETCH_DIM_R: 010 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- + +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/jit/fetch_dim_r_011.phpt b/ext/opcache/tests/jit/fetch_dim_r_011.phpt new file mode 100644 index 0000000000000..3ef3733f19c00 --- /dev/null +++ b/ext/opcache/tests/jit/fetch_dim_r_011.phpt @@ -0,0 +1,18 @@ +--TEST-- +JIT FETCH_DIM_R: 011 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- + +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/jit/fetch_dim_w_003.phpt b/ext/opcache/tests/jit/fetch_dim_w_003.phpt new file mode 100644 index 0000000000000..33fc2ccbb8459 --- /dev/null +++ b/ext/opcache/tests/jit/fetch_dim_w_003.phpt @@ -0,0 +1,17 @@ +--TEST-- +JIT FETCH_DIM_W: 003 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- + +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/jit/fetch_obj_008.phpt b/ext/opcache/tests/jit/fetch_obj_008.phpt new file mode 100644 index 0000000000000..38c5b8a539889 --- /dev/null +++ b/ext/opcache/tests/jit/fetch_obj_008.phpt @@ -0,0 +1,31 @@ +--TEST-- +JIT: FETCH_OBJ 008 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +prop = "A $e B"; + $a->prop->prop . $a->prop = "C"; + return "test"; + } +} + +$a = new A; +$a->prop = new B; +?> +DONE +--EXPECTF-- +Warning: Undefined variable $e in %sfetch_obj_008.php on line 9 + +Warning: Attempt to read property "prop" on string in %sfetch_obj_008.php on line 10 +DONE diff --git a/ext/opcache/tests/jit/fetch_obj_009.phpt b/ext/opcache/tests/jit/fetch_obj_009.phpt new file mode 100644 index 0000000000000..92d67de08abbf --- /dev/null +++ b/ext/opcache/tests/jit/fetch_obj_009.phpt @@ -0,0 +1,21 @@ +--TEST-- +JIT: FETCH_OBJ 009 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +x[0] = null; + $obj->x > $obj->x[0] = null; + } +} +test(); +?> +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/jit/mod_005.phpt b/ext/opcache/tests/jit/mod_005.phpt new file mode 100644 index 0000000000000..8c90f6b6ef17f --- /dev/null +++ b/ext/opcache/tests/jit/mod_005.phpt @@ -0,0 +1,26 @@ +--TEST-- +JIT MOD: 005 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +opcache.protect_memory=1 +--FILE-- +prop %= 3; + return $test; +} + +var_dump(test2(new Test)); +?> +--EXPECT-- +object(Test)#1 (1) { + ["prop"]=> + int(2) +} diff --git a/ext/opcache/tests/jit/mod_006.phpt b/ext/opcache/tests/jit/mod_006.phpt new file mode 100644 index 0000000000000..b13ef68a8e1ba --- /dev/null +++ b/ext/opcache/tests/jit/mod_006.phpt @@ -0,0 +1,19 @@ +--TEST-- +JIT MOD: 005 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +opcache.protect_memory=1 +--FILE-- + +DONE +--EXPECT-- +DONE \ No newline at end of file diff --git a/ext/opcache/tests/jit/mul_008.phpt b/ext/opcache/tests/jit/mul_008.phpt new file mode 100644 index 0000000000000..d890a86c8f485 --- /dev/null +++ b/ext/opcache/tests/jit/mul_008.phpt @@ -0,0 +1,26 @@ +--TEST-- +JIT MUL: 008 incorrect elimination of type store +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +opcache.protect_memory=1 +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught DivisionByZeroError: Modulo by zero in %smul_008.php:6 +Stack trace: +#0 %smul_008.php(8): foo(%d) +#1 {main} + thrown in %smul_008.php on line 6 diff --git a/ext/opcache/tests/opt/assign_op_001.phpt b/ext/opcache/tests/opt/assign_op_001.phpt new file mode 100644 index 0000000000000..b9db4202b46c0 --- /dev/null +++ b/ext/opcache/tests/opt/assign_op_001.phpt @@ -0,0 +1,30 @@ +--TEST-- +ASSIGN_OP 001: Incrrect optimization of ASSIGN_OP may lead to memory leak +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +--EXPECTF-- +Warning: Undefined variable $a in %sassign_op_001.php on line 4 + +Warning: Undefined variable $a in %sassign_op_001.php on line 4 + +Warning: Undefined array key "b" in %sassign_op_001.php on line 7 + +Fatal error: Uncaught TypeError: Unsupported operand types: array + bool in %sassign_op_001.php:4 +Stack trace: +#0 %sassign_op_001.php(10): test() +#1 {main} + thrown in %sassign_op_001.php on line 4 \ No newline at end of file diff --git a/ext/opcache/tests/opt/dce_012.phpt b/ext/opcache/tests/opt/dce_012.phpt new file mode 100644 index 0000000000000..49cde14b33c33 --- /dev/null +++ b/ext/opcache/tests/opt/dce_012.phpt @@ -0,0 +1,26 @@ +--TEST-- +Incorrect DCE of constructor DO_FCALL +--FILE-- +orop1 = 'abc'; + } + + foreach (range(0, 6) as $levels) { + print "$levels level" . ($levels == C ? "" : "s") . "aaa"; + } + + $obj->prop1 = null; +} +test(); +?> +--EXPECTF-- +Fatal error: Uncaught Error: Undefined constant "C" in %sdce_012.php:11 +Stack trace: +#0 %sdce_012.php(16): test() +#1 {main} + thrown in %sdce_012.php on line 11 diff --git a/ext/opcache/tests/opt/inference_002.phpt b/ext/opcache/tests/opt/inference_002.phpt new file mode 100644 index 0000000000000..70412426c2fcc --- /dev/null +++ b/ext/opcache/tests/opt/inference_002.phpt @@ -0,0 +1,15 @@ +--TEST-- +Type inference 002: Type inference for INIT_ARRAY with invalid index +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- +&$x]); +?> +--EXPECTF-- +Fatal error: Uncaught TypeError: Illegal offset type in %sinference_002.php:2 +Stack trace: +#0 {main} + thrown in %sinference_002.php on line 2 \ No newline at end of file diff --git a/ext/opcache/tests/opt/jmp_002.phpt b/ext/opcache/tests/opt/jmp_002.phpt new file mode 100644 index 0000000000000..cd7f05b225dac --- /dev/null +++ b/ext/opcache/tests/opt/jmp_002.phpt @@ -0,0 +1,13 @@ +--TEST-- +JMP 002: JMP around unreachable FREE +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECT-- +DONE diff --git a/ext/opcache/tests/opt/sccp_034.phpt b/ext/opcache/tests/opt/sccp_034.phpt new file mode 100644 index 0000000000000..8fafc89178a64 --- /dev/null +++ b/ext/opcache/tests/opt/sccp_034.phpt @@ -0,0 +1,16 @@ +--TEST-- +SCCP 034: memory leak +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECTF-- +Warning: Undefined variable $y in %ssccp_034.php on line 2 + +Warning: Undefined variable $y in %ssccp_034.php on line 2 +DONE diff --git a/ext/opcache/tests/opt/sccp_035.phpt b/ext/opcache/tests/opt/sccp_035.phpt new file mode 100644 index 0000000000000..86965b13b5f3d --- /dev/null +++ b/ext/opcache/tests/opt/sccp_035.phpt @@ -0,0 +1,17 @@ +--TEST-- +SCCP 035: memory leak +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- +$b = ~$b = $a=''; + $obj->$a--; +} +?> +DONE +--EXPECT-- +DONE diff --git a/ext/openssl/tests/openssl_x509_checkpurpose_basic.phpt b/ext/openssl/tests/openssl_x509_checkpurpose_basic.phpt index 7071677e947b7..d09317b1d22f7 100644 --- a/ext/openssl/tests/openssl_x509_checkpurpose_basic.phpt +++ b/ext/openssl/tests/openssl_x509_checkpurpose_basic.phpt @@ -9,10 +9,14 @@ openssl ?> --FILE-- saveCaCert(__DIR__ . "/san-cert.pem"); + $cert = "file://" . __DIR__ . "/cert.crt"; $bert = "file://" . __DIR__ . "/bug41033.pem"; $sert = "file://" . __DIR__ . "/san-cert.pem"; -$cpca = __DIR__ . "/san-ca.pem"; +$cpca = __DIR__ . "/san-cert.pem"; $utfl = __DIR__ . "/sni_server_uk.pem"; $rcrt = openssl_x509_read($cert); @@ -85,6 +89,10 @@ var_dump(openssl_x509_checkpurpose($sert, X509_PURPOSE_SMIME_ENCRYPT, array($cpc var_dump(openssl_x509_checkpurpose($sert, X509_PURPOSE_CRL_SIGN, array($cpca), $utfl)); var_dump(openssl_x509_checkpurpose($sert, X509_PURPOSE_ANY, array($cpca), $utfl)); ?> +--CLEAN-- + --EXPECT-- bool(false) bool(false) diff --git a/ext/openssl/tests/san-ca.pem b/ext/openssl/tests/san-ca.pem deleted file mode 100644 index 88682ba2dcf65..0000000000000 --- a/ext/openssl/tests/san-ca.pem +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICYTCCAcqgAwIBAgIJAIaqxtY5dwjtMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNV -BAYTAlVTMQswCQYDVQQIEwJNTjEUMBIGA1UEBxMLTWlubmVhcG9saXMxITAfBgNV -BAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDAeFw0xMzA5MjQwODA1NTFaFw0y -MTEyMTEwODA1NTFaMFMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNTjEUMBIGA1UE -BxMLTWlubmVhcG9saXMxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRl -ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsFGqfbU/8D+KjroQl4XMyt9m -dcSP7iZtqphOu9nVZxYAAqfaqj8FnC/pwYV3TU6ZHndLTQAllwYT3sQBQPPGmZQ9 -clSIMEL003t3pi4ZVXkttG6Vvr+Z9PBcHhlKLQ7WMHnn4qctllWXTSoyTQpkETF3 -Fc3mrG5G37BhoUno7NECAwEAAaM9MDswOQYDVR0RBDIwMIILZXhhbXBsZS5vcmeC -D3d3dy5leGFtcGxlLm9yZ4IQdGVzdC5leGFtcGxlLm9yZzANBgkqhkiG9w0BAQUF -AAOBgQBf/FZhzheIcQJ+dyTk8xQ/nJLvpmBhbd1LNtfwk/MsC9UHsz4QXs9sBw1k -rH0FjoqgM6avj7zKHJFTj6q7Rd+OX5V4HynYPhX67sWbN3KWEHffL98nGGd/bo3X -pSjNk5vnyKYiwdUUe11Ac9csh0HcSBbhOYjy0T/i9AlQcKbuCg== ------END CERTIFICATE----- diff --git a/ext/openssl/tests/san-cert.pem b/ext/openssl/tests/san-cert.pem deleted file mode 100644 index 923d490e72fd3..0000000000000 --- a/ext/openssl/tests/san-cert.pem +++ /dev/null @@ -1,31 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICYTCCAcqgAwIBAgIJAIaqxtY5dwjtMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNV -BAYTAlVTMQswCQYDVQQIEwJNTjEUMBIGA1UEBxMLTWlubmVhcG9saXMxITAfBgNV -BAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDAeFw0xMzA5MjQwODA1NTFaFw0y -MTEyMTEwODA1NTFaMFMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNTjEUMBIGA1UE -BxMLTWlubmVhcG9saXMxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRl -ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsFGqfbU/8D+KjroQl4XMyt9m -dcSP7iZtqphOu9nVZxYAAqfaqj8FnC/pwYV3TU6ZHndLTQAllwYT3sQBQPPGmZQ9 -clSIMEL003t3pi4ZVXkttG6Vvr+Z9PBcHhlKLQ7WMHnn4qctllWXTSoyTQpkETF3 -Fc3mrG5G37BhoUno7NECAwEAAaM9MDswOQYDVR0RBDIwMIILZXhhbXBsZS5vcmeC -D3d3dy5leGFtcGxlLm9yZ4IQdGVzdC5leGFtcGxlLm9yZzANBgkqhkiG9w0BAQUF -AAOBgQBf/FZhzheIcQJ+dyTk8xQ/nJLvpmBhbd1LNtfwk/MsC9UHsz4QXs9sBw1k -rH0FjoqgM6avj7zKHJFTj6q7Rd+OX5V4HynYPhX67sWbN3KWEHffL98nGGd/bo3X -pSjNk5vnyKYiwdUUe11Ac9csh0HcSBbhOYjy0T/i9AlQcKbuCg== ------END CERTIFICATE----- ------BEGIN PRIVATE KEY----- -MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALBRqn21P/A/io66 -EJeFzMrfZnXEj+4mbaqYTrvZ1WcWAAKn2qo/BZwv6cGFd01OmR53S00AJZcGE97E -AUDzxpmUPXJUiDBC9NN7d6YuGVV5LbRulb6/mfTwXB4ZSi0O1jB55+KnLZZVl00q -Mk0KZBExdxXN5qxuRt+wYaFJ6OzRAgMBAAECgYB11e5iWvqjPmQEZRdnnJU0VD8u -n7ItT+Nk6qtb4gY8Abj6DWIW+01th5vqqJ8FvGyartFVYa69kuM+srG/zevAZWeu -fGZtwiwZR4DRSyRcPp4rnNiksK3dkAZA6UewmRDPv8uyHJlXc5i+Ft1ILJ5Q5jgn -UkC4z3EJP5Se9KZywQJBAOO4lRq42wLsYr2SDrQDSs4leie3FKc2bgvjF7Djosh1 -ZYbf55F5b9w1zgnccmni2HkqOnyFu4SKarmXyCsYxrkCQQDGNvnUh7/zZswrdWZ/ -PMp9zVDTh/5Oc2B4ByNLw1ERDwYhjchKgPRlQvn4cp3Pwf3UYPQ/8XGXzzEJey3A -r0rZAkBf/tDEOgcBPXsGZQrTscuYCU5sbY5ESvqrAilbhSp7DJom+D5bIfEYyIm5 -uHd20Yzlzvpmwc1huyPwZt6X5FLpAkATDReoGMAXSesXxjnqwtIHk2NQYYLM0YQV -JUJ8NrKk/Bevw+vbVVeoH+7ctU97t36JGiR/vNoZKD3jVmaIXZDJAkEA4wJbwzIo -L32mu9VmZa7wjmfkraQEmXTPaA5D9lNC0AwRTgkj+x2Qe1vawNblNK9PPLBDdplQ -L//53ADq/wv5rA== ------END PRIVATE KEY----- diff --git a/ext/pdo/pdo.stub.php b/ext/pdo/pdo.stub.php index 39a508bafcb15..ebe81b7a51ad8 100644 --- a/ext/pdo/pdo.stub.php +++ b/ext/pdo/pdo.stub.php @@ -4,6 +4,8 @@ class PDOException extends RuntimeException { + /** @var int|string */ + protected $code = 0; public ?array $errorInfo = null; } diff --git a/ext/pdo/pdo_arginfo.h b/ext/pdo/pdo_arginfo.h index d4c74eef624f8..72eda0c3ae99a 100644 --- a/ext/pdo/pdo_arginfo.h +++ b/ext/pdo/pdo_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 52ee252fdfc80d4d076f1c49842e333c27ed5102 */ + * Stub hash: 8d975a20d009e827f8d72ac19b94b55870b6bf9c */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pdo_drivers, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -25,6 +25,12 @@ static zend_class_entry *register_class_PDOException(zend_class_entry *class_ent INIT_CLASS_ENTRY(ce, "PDOException", class_PDOException_methods); class_entry = zend_register_internal_class_ex(&ce, class_entry_RuntimeException); + zval property_code_default_value; + ZVAL_LONG(&property_code_default_value, 0); + zend_string *property_code_name = zend_string_init("code", sizeof("code") - 1, 1); + zend_declare_property_ex(class_entry, property_code_name, &property_code_default_value, ZEND_ACC_PROTECTED, NULL); + zend_string_release(property_code_name); + zval property_errorInfo_default_value; ZVAL_NULL(&property_errorInfo_default_value); zend_string *property_errorInfo_name = zend_string_init("errorInfo", sizeof("errorInfo") - 1, 1); diff --git a/ext/pdo/tests/bug_36798.phpt b/ext/pdo/tests/bug_36798.phpt index bfea814de9664..dea1a5b92a23c 100644 --- a/ext/pdo/tests/bug_36798.phpt +++ b/ext/pdo/tests/bug_36798.phpt @@ -11,7 +11,8 @@ PDOTest::skip(); if (!strncasecmp(getenv('PDOTEST_DSN'), 'oci', strlen('oci'))){ if (!strpos(strtolower(getenv('PDOTEST_DSN')), 'charset=we8mswin1252')) die('skip expected output valid for Oracle with WE8MSWIN1252 character set'); - +} elseif (!strncasecmp(getenv('PDOTEST_DSN'), 'dblib', strlen('dblib'))) { + die('skip not for pdo_dblib'); } ?> diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c index 09083ccfc3057..c814324af9705 100644 --- a/ext/pdo_mysql/mysql_driver.c +++ b/ext/pdo_mysql/mysql_driver.c @@ -544,7 +544,7 @@ static int pdo_mysql_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_ ZVAL_BOOL(return_value, H->local_infile); break; -#if MYSQL_VERSION_ID >= 80021 || defined(PDO_USE_MYSQLND) +#if (MYSQL_VERSION_ID >= 80021 && !defined(MARIADB_BASE_VERSION)) || defined(PDO_USE_MYSQLND) case PDO_MYSQL_ATTR_LOCAL_INFILE_DIRECTORY: { const char* local_infile_directory = NULL; @@ -765,7 +765,7 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) #endif } -#if MYSQL_VERSION_ID >= 80021 || defined(PDO_USE_MYSQLND) +#if (MYSQL_VERSION_ID >= 80021 && !defined(MARIADB_BASE_VERSION)) || defined(PDO_USE_MYSQLND) zend_string *local_infile_directory = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_LOCAL_INFILE_DIRECTORY, NULL); if (local_infile_directory && !php_check_open_basedir(ZSTR_VAL(local_infile_directory))) { if (mysql_options(H->server, MYSQL_OPT_LOAD_DATA_LOCAL_DIR, (const char *)ZSTR_VAL(local_infile_directory))) { diff --git a/ext/pdo_mysql/tests/unsigned_bigint.phpt b/ext/pdo_mysql/tests/unsigned_bigint.phpt new file mode 100644 index 0000000000000..e2fc9604f24ae --- /dev/null +++ b/ext/pdo_mysql/tests/unsigned_bigint.phpt @@ -0,0 +1,49 @@ +--TEST-- +Bug GH-7837 (large bigints may be truncated) +--EXTENSIONS-- +pdo +pdo_mysql +mysqlnd +--SKIPIF-- + +--FILE-- +query("DROP TABLE IF EXISTS $tbl"); +$pdo->query("CREATE TABLE $tbl (`ubigint` bigint unsigned NOT NULL) ENGINE=InnoDB"); +$pdo->query("INSERT INTO $tbl (`ubigint`) VALUES (18446744073709551615)"); +$pdo->query("INSERT INTO $tbl (`ubigint`) VALUES (9223372036854775808)"); +$pdo->query("INSERT INTO $tbl (`ubigint`) VALUES (1)"); +$result = $pdo->query("SELECT ubigint FROM $tbl")->fetchAll(PDO::FETCH_ASSOC); +var_dump($result); +?> +--CLEAN-- + +--EXPECT-- +array(3) { + [0]=> + array(1) { + ["ubigint"]=> + string(20) "18446744073709551615" + } + [1]=> + array(1) { + ["ubigint"]=> + string(19) "9223372036854775808" + } + [2]=> + array(1) { + ["ubigint"]=> + int(1) + } +} diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index be9e8c012252e..54bf7ede6bfaa 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -87,7 +87,7 @@ int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char * } if (msg) { - einfo->errmsg = estrdup(msg); + einfo->errmsg = pestrdup(msg, dbh->is_persistent); } else if (errmsg) { einfo->errmsg = _pdo_pgsql_trim_message(errmsg, dbh->is_persistent); diff --git a/ext/pdo_pgsql/tests/gh7723.phpt b/ext/pdo_pgsql/tests/gh7723.phpt new file mode 100644 index 0000000000000..bbbf5fd5bc21c --- /dev/null +++ b/ext/pdo_pgsql/tests/gh7723.phpt @@ -0,0 +1,30 @@ +--TEST-- +GitHub #7723 (Fix error message allocation of PDO PgSQL) +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_PERSISTENT, true); +$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); + +$st = $db->prepare('select 1'); +for ($i = 0; ++$i <= 2;) { + try { + $st->bindValue(':invalid', $i); + } catch (PDOException $e) { + echo $e->getMessage() . "\n"; + } +} +?> +--EXPECT-- +SQLSTATE[HY093]: Invalid parameter number: :invalid +SQLSTATE[HY093]: Invalid parameter number: :invalid diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 2134d9aa72f2f..d2d84bf0af1e6 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -4751,7 +4751,7 @@ ZEND_METHOD(ReflectionClass, isInstantiable) RETURN_THROWS(); } GET_REFLECTION_OBJECT_PTR(ce); - if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) { + if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_ENUM)) { RETURN_FALSE; } @@ -4776,7 +4776,7 @@ ZEND_METHOD(ReflectionClass, isCloneable) RETURN_THROWS(); } GET_REFLECTION_OBJECT_PTR(ce); - if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) { + if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_ENUM)) { RETURN_FALSE; } if (!Z_ISUNDEF(intern->obj)) { diff --git a/ext/reflection/tests/bug81681.phpt b/ext/reflection/tests/bug81681.phpt new file mode 100644 index 0000000000000..6b1c2278163e6 --- /dev/null +++ b/ext/reflection/tests/bug81681.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #81681 (ReflectionEnum throwing exceptions) +--FILE-- +isInstantiable()); +var_dump($reflectionEnum->isCloneable()); +?> +--EXPECT-- +bool(false) +bool(false) diff --git a/ext/simplexml/simplexml.stub.php b/ext/simplexml/simplexml.stub.php index a115c8b2defeb..4735573521587 100644 --- a/ext/simplexml/simplexml.stub.php +++ b/ext/simplexml/simplexml.stub.php @@ -44,7 +44,7 @@ public function __construct(string $data, int $options = 0, bool $dataIsURL = fa public function addChild(string $qualifiedName, ?string $value = null, ?string $namespace = null): ?SimpleXMLElement {} /** @tentative-return-type */ - public function addAttribute(string $qualifiedName, ?string $value = null, ?string $namespace = null): void {} + public function addAttribute(string $qualifiedName, string $value, ?string $namespace = null): void {} /** @tentative-return-type */ public function getName(): string {} diff --git a/ext/simplexml/simplexml_arginfo.h b/ext/simplexml/simplexml_arginfo.h index 881051514c595..f6100eb243e31 100644 --- a/ext/simplexml/simplexml_arginfo.h +++ b/ext/simplexml/simplexml_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 46da4d24787a5f975eebeaab3872eb29273a9625 */ + * Stub hash: 06c88dc2fb5582a6d21c11aee6ac0a0538e70cbc */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_simplexml_load_file, 0, 1, SimpleXMLElement, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) @@ -67,9 +67,9 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_SimpleXMLElement_ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, namespace, IS_STRING, 1, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement_addAttribute, 0, 1, IS_VOID, 0) +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SimpleXMLElement_addAttribute, 0, 2, IS_VOID, 0) ZEND_ARG_TYPE_INFO(0, qualifiedName, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, namespace, IS_STRING, 1, "null") ZEND_END_ARG_INFO() diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index f0917501751f5..a6ef3b92454d3 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -1999,7 +1999,7 @@ PHP_MINIT_FUNCTION(snmp) init_snmp("snmpapp"); /* net-snmp corrupts the CTYPE locale during initialization. */ - setlocale(LC_CTYPE, "C"); + zend_reset_lc_ctype_locale(); #ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE /* Prevent update of the snmpapp.conf file */ diff --git a/ext/sockets/config.m4 b/ext/sockets/config.m4 index b78186ee11ba6..d4f92082c3b2d 100644 --- a/ext/sockets/config.m4 +++ b/ext/sockets/config.m4 @@ -62,6 +62,34 @@ if test "$PHP_SOCKETS" != "no"; then AC_DEFINE(HAVE_AI_IDN,1,[Whether you have AI_IDN]) fi + dnl Check for struct ucred + dnl checking the header is not enough (eg DragonFlyBSD) + AC_CACHE_CHECK([if ancillary credentials uses ucred],[ac_cv_ucred], + [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include + ]], [[struct ucred u = {.gid = 0};]])], + [ac_cv_ucred=yes], [ac_cv_ucred=no]) + ]) + + if test "$ac_cv_ucred" = yes; then + AC_DEFINE(ANC_CREDS_UCRED,1,[Uses ucred struct]) + fi + + dnl Check for struct cmsgcred + AC_CACHE_CHECK([if ancillary credentials uses cmsgcred],[ac_cv_cmsgcred], + [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include + ]], [[struct cmsgcred c = {0};]])], + [ac_cv_cmsgcred=yes], [ac_cv_cmsgcred=no]) + ]) + + if test "$ac_cv_cmsgcred" = yes; then + AC_DEFINE(ANC_CREDS_CMSGCRED,1,[Uses cmsgcred struct]) + fi + + PHP_SOCKETS_CFLAGS=-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 case $host_alias in *darwin*) PHP_SOCKETS_CFLAGS="$PHP_SOCKETS_CFLAGS -D__APPLE_USE_RFC_3542" diff --git a/ext/sockets/conversions.c b/ext/sockets/conversions.c index ba5b1d8a5ad67..773ac5f3e02cd 100644 --- a/ext/sockets/conversions.c +++ b/ext/sockets/conversions.c @@ -1297,13 +1297,20 @@ void to_zval_read_in6_pktinfo(const char *data, zval *zv, res_context *ctx) } #endif -/* CONVERSIONS for struct ucred */ +/* CONVERSIONS for struct ucred/cmsgcred */ #ifdef SO_PASSCRED static const field_descriptor descriptors_ucred[] = { +#if defined(ANC_CREDS_UCRED) {"pid", sizeof("pid"), 1, offsetof(struct ucred, pid), from_zval_write_pid_t, to_zval_read_pid_t}, {"uid", sizeof("uid"), 1, offsetof(struct ucred, uid), from_zval_write_uid_t, to_zval_read_uid_t}, /* assume the type gid_t is the same as uid_t: */ {"gid", sizeof("gid"), 1, offsetof(struct ucred, gid), from_zval_write_uid_t, to_zval_read_uid_t}, +#elif defined(ANC_CREDS_CMSGCRED) + {"pid", sizeof("pid"), 1, offsetof(struct cmsgcred, cmcred_pid), from_zval_write_pid_t, to_zval_read_pid_t}, + {"uid", sizeof("uid"), 1, offsetof(struct cmsgcred, cmcred_uid), from_zval_write_uid_t, to_zval_read_uid_t}, + /* assume the type gid_t is the same as uid_t: */ + {"gid", sizeof("gid"), 1, offsetof(struct cmsgcred, cmcred_gid), from_zval_write_uid_t, to_zval_read_uid_t}, +#endif {0} }; void from_zval_write_ucred(const zval *container, char *ucred_c, ser_context *ctx) diff --git a/ext/sockets/multicast.c b/ext/sockets/multicast.c index 0b2f10d09fb6f..ef32661be09ff 100644 --- a/ext/sockets/multicast.c +++ b/ext/sockets/multicast.c @@ -718,7 +718,7 @@ int php_if_index_to_addr4(unsigned if_index, php_socket *php_sock, struct in_add return SUCCESS; } -#if !defined(ifr_ifindex) && defined(ifr_index) +#if !defined(ifr_ifindex) && (defined(ifr_index) || defined(__HAIKU__)) #define ifr_ifindex ifr_index #endif @@ -784,7 +784,7 @@ int php_add4_to_if_index(struct in_addr *addr, php_socket *php_sock, unsigned *i } for (p = if_conf.ifc_buf; - p < if_conf.ifc_buf + if_conf.ifc_len; + p < ((char *)if_conf.ifc_buf) + if_conf.ifc_len; p += entry_len) { /* p may be misaligned on macos. */ struct ifreq cur_req; diff --git a/ext/sockets/sendrecvmsg.c b/ext/sockets/sendrecvmsg.c index bd24eae9418a1..7029478486cb3 100644 --- a/ext/sockets/sendrecvmsg.c +++ b/ext/sockets/sendrecvmsg.c @@ -121,8 +121,13 @@ static void init_ancillary_registry(void) #endif #ifdef SO_PASSCRED +#ifdef ANC_CREDS_UCRED PUT_ENTRY(sizeof(struct ucred), 0, 0, from_zval_write_ucred, to_zval_read_ucred, SOL_SOCKET, SCM_CREDENTIALS); +#else + PUT_ENTRY(sizeof(struct cmsgcred), 0, 0, from_zval_write_ucred, + to_zval_read_ucred, SOL_SOCKET, SCM_CREDS); +#endif #endif #ifdef SCM_RIGHTS @@ -436,7 +441,11 @@ void php_socket_sendrecvmsg_init(INIT_FUNC_ARGS) REGISTER_LONG_CONSTANT("SCM_RIGHTS", SCM_RIGHTS, CONST_CS | CONST_PERSISTENT); #endif #ifdef SO_PASSCRED +#ifdef SCM_CREDENTIALS REGISTER_LONG_CONSTANT("SCM_CREDENTIALS", SCM_CREDENTIALS, CONST_CS | CONST_PERSISTENT); +#else + REGISTER_LONG_CONSTANT("SCM_CREDS", SCM_CREDS, CONST_CS | CONST_PERSISTENT); +#endif REGISTER_LONG_CONSTANT("SO_PASSCRED", SO_PASSCRED, CONST_CS | CONST_PERSISTENT); #endif diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index a82300114c214..8a46446785f45 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -463,7 +463,9 @@ static PHP_MINIT_FUNCTION(sockets) REGISTER_LONG_CONSTANT("SOCK_DGRAM", SOCK_DGRAM, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SOCK_RAW", SOCK_RAW, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SOCK_SEQPACKET",SOCK_SEQPACKET, CONST_CS | CONST_PERSISTENT); +#ifdef SOCK_RDM REGISTER_LONG_CONSTANT("SOCK_RDM", SOCK_RDM, CONST_CS | CONST_PERSISTENT); +#endif REGISTER_LONG_CONSTANT("MSG_OOB", MSG_OOB, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MSG_WAITALL", MSG_WAITALL, CONST_CS | CONST_PERSISTENT); diff --git a/ext/sockets/tests/socket_cmsg_credentials.phpt b/ext/sockets/tests/socket_cmsg_credentials.phpt index aaeff989fc37b..7402c9437c2b2 100644 --- a/ext/sockets/tests/socket_cmsg_credentials.phpt +++ b/ext/sockets/tests/socket_cmsg_credentials.phpt @@ -14,10 +14,6 @@ die('skip not for AIX'); if (!defined('SO_PASSCRED')) { die('skip SO_PASSCRED is not defined'); } ---CLEAN-- - +--CLEAN-- +type) { case SPL_FS_INFO: - intern->path = zend_string_copy(source->path); - intern->file_name = zend_string_copy(source->file_name); + if (source->path != NULL) { + intern->path = zend_string_copy(source->path); + } + if (source->file_name != NULL) { + intern->file_name = zend_string_copy(source->file_name); + } break; case SPL_FS_DIR: spl_filesystem_dir_open(intern, source->path); @@ -1940,6 +1944,8 @@ static int spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_obje /* 1) use fgetcsv? 2) overloaded call the function, 3) do it directly */ if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) { + spl_filesystem_file_free_line(intern); + if (php_stream_eof(intern->u.file.stream)) { if (!silent) { zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", ZSTR_VAL(intern->file_name)); diff --git a/ext/spl/spl_observer.stub.php b/ext/spl/spl_observer.stub.php index e5ea360354f4d..ed327aa7aad6b 100644 --- a/ext/spl/spl_observer.stub.php +++ b/ext/spl/spl_observer.stub.php @@ -90,7 +90,7 @@ public function offsetGet($object): mixed {} * @implementation-alias SplObjectStorage::attach * @no-verify Cannot specify arg type because ArrayAccess does not */ - public function offsetSet(mixed $object, mixed $info = null): void {} + public function offsetSet($object, mixed $info = null): void {} /** * @param object $object diff --git a/ext/spl/spl_observer_arginfo.h b/ext/spl/spl_observer_arginfo.h index 5e9044a088f1e..94991119cb6f1 100644 --- a/ext/spl/spl_observer_arginfo.h +++ b/ext/spl/spl_observer_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a3c87f5b7edd257e25d6651628dd9896e14f5715 */ + * Stub hash: 63dde3294f600164805befd79b1f670fbfb23571 */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SplObserver_update, 0, 1, IS_VOID, 0) ZEND_ARG_OBJ_INFO(0, subject, SplSubject, 0) @@ -75,7 +75,7 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SplObjectStorage ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_SplObjectStorage_offsetSet, 0, 1, IS_VOID, 0) - ZEND_ARG_TYPE_INFO(0, object, IS_MIXED, 0) + ZEND_ARG_INFO(0, object) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, info, IS_MIXED, 0, "null") ZEND_END_ARG_INFO() diff --git a/ext/spl/tests/bug75917.phpt b/ext/spl/tests/bug75917.phpt new file mode 100644 index 0000000000000..c9bc02869c2d1 --- /dev/null +++ b/ext/spl/tests/bug75917.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #75917 (SplFileObject::seek broken with CSV flags) +--FILE-- +fputcsv($row); +} +$tmp->setFlags(0); +$tmp->seek(23); +var_dump($tmp->current()); + +$tmp->setFlags(SplFileObject::READ_CSV | SplFileObject::SKIP_EMPTY); +$tmp->seek(23); +var_dump($tmp->current()); +?> +--EXPECT-- +bool(false) +bool(false) diff --git a/ext/spl/tests/gh7809.phpt b/ext/spl/tests/gh7809.phpt new file mode 100644 index 0000000000000..6406bef6c1438 --- /dev/null +++ b/ext/spl/tests/gh7809.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug GH-7809 (Cloning a faked SplFileInfo object may segfault) +--FILE-- + +--EXPECT-- diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 73d92fd447f19..23f736d200905 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -528,6 +528,7 @@ PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */ * to the value in startup environment */ if (BG(locale_changed)) { setlocale(LC_ALL, "C"); + zend_reset_lc_ctype_locale(); zend_update_current_locale(); if (BG(ctype_string)) { zend_string_release_ex(BG(ctype_string), 0); diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 1719b1453795a..3a5f482456666 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -1860,7 +1860,7 @@ function rawurlencode(string $string): string {} function rawurldecode(string $string): string {} /** - * @param resource $context + * @param resource|null $context * @return array|false * @refcount 1 */ diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index ab7776d630919..693b2644cbf5b 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 96393b26861733e5c7fc9a12095a29c07ed73928 */ + * Stub hash: 87ed2b04b9b46ce3df78d6f9d6d62bd6b2ae8fe5 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) diff --git a/ext/standard/dns.c b/ext/standard/dns.c index e88e5a79db114..6d22e644a8eff 100644 --- a/ext/standard/dns.c +++ b/ext/standard/dns.c @@ -182,14 +182,14 @@ static zend_string *php_gethostbyaddr(char *ip) if (inet_pton(AF_INET6, ip, &sa6.sin6_addr)) { sa6.sin6_family = AF_INET6; - if (getnameinfo((struct sockaddr *)&sa6, sizeof(sa6), out, sizeof(out), NULL, 0, NI_NAMEREQD) < 0) { + if (getnameinfo((struct sockaddr *)&sa6, sizeof(sa6), out, sizeof(out), NULL, 0, NI_NAMEREQD) != 0) { return zend_string_init(ip, strlen(ip), 0); } return zend_string_init(out, strlen(out), 0); } else if (inet_pton(AF_INET, ip, &sa4.sin_addr)) { sa4.sin_family = AF_INET; - if (getnameinfo((struct sockaddr *)&sa4, sizeof(sa4), out, sizeof(out), NULL, 0, NI_NAMEREQD) < 0) { + if (getnameinfo((struct sockaddr *)&sa4, sizeof(sa4), out, sizeof(out), NULL, 0, NI_NAMEREQD) != 0) { return zend_string_init(ip, strlen(ip), 0); } return zend_string_init(out, strlen(out), 0); diff --git a/ext/standard/info.c b/ext/standard/info.c index 395110d25f218..651bf3ae3f6d7 100644 --- a/ext/standard/info.c +++ b/ext/standard/info.c @@ -268,11 +268,34 @@ char* php_get_windows_name() if (VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && osvi.dwMajorVersion >= 10) { if (osvi.dwMajorVersion == 10) { - if( osvi.dwMinorVersion == 0 ) { - if( osvi.wProductType == VER_NT_WORKSTATION ) { - major = "Windows 10"; + if (osvi.dwMinorVersion == 0) { + if (osvi.wProductType == VER_NT_WORKSTATION) { + if (osvi.dwBuildNumber >= 22000) { + major = "Windows 11"; + } else { + major = "Windows 10"; + } } else { - major = "Windows Server 2016"; + if (osvi.dwBuildNumber >= 20348) { + major = "Windows Server 2022"; + } else if (osvi.dwBuildNumber >= 19042) { + major = "Windows Server, version 20H2"; + } else if (osvi.dwBuildNumber >= 19041) { + major = "Windows Server, version 2004"; + } else if (osvi.dwBuildNumber >= 18363) { + major = "Windows Server, version 1909"; + } else if (osvi.dwBuildNumber >= 18362) { + major = "Windows Server, version 1903"; + } else if (osvi.dwBuildNumber >= 17763) { + // could also be Windows Server, version 1809, but there's no easy way to tell + major = "Windows Server 2019"; + } else if (osvi.dwBuildNumber >= 17134) { + major = "Windows Server, version 1803"; + } else if (osvi.dwBuildNumber >= 16299) { + major = "Windows Server, version 1709"; + } else { + major = "Windows Server 2016"; + } } } } diff --git a/ext/standard/tests/strings/chunk_split_variation1_32bit.phpt b/ext/standard/tests/strings/chunk_split_variation1_32bit.phpt index b2fd29ad88098..b4bef8add4103 100644 --- a/ext/standard/tests/strings/chunk_split_variation1_32bit.phpt +++ b/ext/standard/tests/strings/chunk_split_variation1_32bit.phpt @@ -17,4 +17,4 @@ var_dump(chunk_split($a,$b,$c)); --EXPECTF-- *** Testing chunk_split() : unexpected large 'end' string argument variation 1 *** -Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d +Fatal error: %rAllowed memory size of %d bytes exhausted%s\(tried to allocate %d bytes\)|Possible integer overflow in memory allocation \(4294901777 \+ 2097152\)%r in %s on line %d diff --git a/ext/standard/tests/strings/chunk_split_variation2_32bit.phpt b/ext/standard/tests/strings/chunk_split_variation2_32bit.phpt index 0f777fbd38605..c83a37f00edb4 100644 --- a/ext/standard/tests/strings/chunk_split_variation2_32bit.phpt +++ b/ext/standard/tests/strings/chunk_split_variation2_32bit.phpt @@ -16,4 +16,4 @@ var_dump(chunk_split($a,$b,$c)); --EXPECTF-- *** Testing chunk_split() : unexpected large 'end' string argument variation 2 *** -Fatal error: Possible integer overflow in memory allocation (65537 * 65537 + 65556) in %s on line %d +Fatal error: Possible integer overflow in memory allocation (65537 * 65537 + %r65556|65560%r) in %s on line %d diff --git a/main/main.c b/main/main.c index 7de295fe84fb3..a0f1a658c661a 100644 --- a/main/main.c +++ b/main/main.c @@ -2087,6 +2087,7 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod zuf.getenv_function = sapi_getenv; zuf.resolve_path_function = php_resolve_path_for_zend; zend_startup(&zuf); + zend_reset_lc_ctype_locale(); zend_update_current_locale(); zend_observer_startup(); diff --git a/main/php_version.h b/main/php_version.h index 44f483c823bf6..2a47f8f63b329 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 -#define PHP_RELEASE_VERSION 1 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.1-dev" -#define PHP_VERSION_ID 80101 +#define PHP_RELEASE_VERSION 2 +#define PHP_EXTRA_VERSION "" +#define PHP_VERSION "8.1.2" +#define PHP_VERSION_ID 80102 diff --git a/sapi/fpm/fpm/zlog.c b/sapi/fpm/fpm/zlog.c index 4808447f5c924..0938f08e89de4 100644 --- a/sapi/fpm/fpm/zlog.c +++ b/sapi/fpm/fpm/zlog.c @@ -637,10 +637,10 @@ zlog_bool zlog_stream_set_msg_suffix( if (suffix != NULL) { stream->msg_suffix_len = strlen(suffix); len = stream->msg_suffix_len + 1; - stream->msg_suffix = malloc(len); if (stream->msg_suffix != NULL) { free(stream->msg_suffix); } + stream->msg_suffix = malloc(len); if (stream->msg_suffix == NULL) { return ZLOG_FALSE; } @@ -650,10 +650,10 @@ zlog_bool zlog_stream_set_msg_suffix( if (final_suffix != NULL) { stream->msg_final_suffix_len = strlen(final_suffix); len = stream->msg_final_suffix_len + 1; - stream->msg_final_suffix = malloc(len); if (stream->msg_final_suffix != NULL) { free(stream->msg_suffix); } + stream->msg_final_suffix = malloc(len); if (stream->msg_final_suffix == NULL) { return ZLOG_FALSE; }