diff --git a/Zend/tests/gh10168_1.phpt b/Zend/tests/gh10168_1.phpt index 6433453ed244..5f491ff296db 100644 --- a/Zend/tests/gh10168_1.phpt +++ b/Zend/tests/gh10168_1.phpt @@ -7,7 +7,7 @@ class Test { static $instances; public function __construct() { - (self::$instances[NULL] = $this) > 0; + var_dump(self::$instances[NULL] = $this); var_dump(self::$instances); } @@ -19,14 +19,15 @@ new Test(); new Test(); ?> ---EXPECTF-- -Notice: Object of class Test could not be converted to int in %s on line %d +--EXPECT-- +object(Test)#1 (0) { +} array(1) { [""]=> object(Test)#1 (0) { } } - -Notice: Object of class Test could not be converted to int in %s on line %d +object(Test)#2 (0) { +} array(0) { } diff --git a/Zend/tests/gh10168_10.phpt b/Zend/tests/gh10168_10.phpt new file mode 100644 index 000000000000..38b81bd9e9ba --- /dev/null +++ b/Zend/tests/gh10168_10.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed static prop ref +--FILE-- + +--EXPECT-- +object(Test)#1 (0) { +} +NULL diff --git a/Zend/tests/gh10168_11.phpt b/Zend/tests/gh10168_11.phpt new file mode 100644 index 000000000000..3afcd7727e7e --- /dev/null +++ b/Zend/tests/gh10168_11.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): global by ref val error +--FILE-- + +--EXPECTF-- +Notice: Only variables should be assigned by reference in %s on line %d +int(42) diff --git a/Zend/tests/gh10168_12.phpt b/Zend/tests/gh10168_12.phpt new file mode 100644 index 000000000000..36400f90b549 --- /dev/null +++ b/Zend/tests/gh10168_12.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign static prop ref +--FILE-- + +--EXPECT-- +object(Test)#1 (0) { +} +NULL diff --git a/Zend/tests/gh10168_13.phpt b/Zend/tests/gh10168_13.phpt new file mode 100644 index 000000000000..94f7d67d6443 --- /dev/null +++ b/Zend/tests/gh10168_13.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign prop ref +--FILE-- +storage = &$this); + } + + function __destruct() { + global $box; + var_dump($box->storage); + $box->storage = null; + } +} +new Test(); +new Test(); + +?> +--EXPECT-- +object(Test)#2 (0) { +} +object(Test)#3 (0) { +} +NULL +NULL diff --git a/Zend/tests/gh10168_14.phpt b/Zend/tests/gh10168_14.phpt new file mode 100644 index 000000000000..62c4f0e9b93e --- /dev/null +++ b/Zend/tests/gh10168_14.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed prop ref +--FILE-- +storage = &$this); + } + + function __destruct() { + global $box; + var_dump($box->storage); + $box->storage = null; + } +} +new Test(); +new Test(); + +?> +--EXPECT-- +object(Test)#2 (0) { +} +object(Test)#3 (0) { +} +NULL +NULL diff --git a/Zend/tests/gh10168_15.phpt b/Zend/tests/gh10168_15.phpt new file mode 100644 index 000000000000..4185f352d460 --- /dev/null +++ b/Zend/tests/gh10168_15.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): global by ref +--FILE-- + +--EXPECT-- +int(42) diff --git a/Zend/tests/gh10168_2.phpt b/Zend/tests/gh10168_2.phpt index abab8b72f1cb..aa6c0921e279 100644 --- a/Zend/tests/gh10168_2.phpt +++ b/Zend/tests/gh10168_2.phpt @@ -8,7 +8,7 @@ $a = null; class Test { public function __construct() { - ($GLOBALS['a'] = $this) > 0; + var_dump($GLOBALS['a'] = $this); // Destructor called after comparison, so a will be NULL var_dump($GLOBALS['a']); } @@ -22,11 +22,12 @@ new Test(); ?> --EXPECTF-- -Notice: Object of class Test could not be converted to int in %s on line %d object(Test)#1 (0) { } - -Notice: Object of class Test could not be converted to int in %s on line %d +object(Test)#1 (0) { +} +object(Test)#2 (0) { +} Warning: Undefined global variable $a in %s on line %d NULL diff --git a/Zend/tests/gh10168_3.phpt b/Zend/tests/gh10168_3.phpt index 35c8ed42f847..651ff9077e1d 100644 --- a/Zend/tests/gh10168_3.phpt +++ b/Zend/tests/gh10168_3.phpt @@ -1,6 +1,5 @@ --TEST-- -GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed prop ---XFAIL-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed static prop --FILE-- ---EXPECTF-- +--EXPECT-- object(Test)#1 (0) { } object(Test)#2 (0) { } +object(Test)#2 (0) { +} +NULL diff --git a/Zend/tests/gh10168_4.phpt b/Zend/tests/gh10168_4.phpt new file mode 100644 index 000000000000..d931a6be9a55 --- /dev/null +++ b/Zend/tests/gh10168_4.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign prop +--FILE-- +storage = $this); + } + + function __destruct() { + global $box; + var_dump($box->storage); + $box->storage = null; + } +} +new Test(); +new Test(); + +?> +--EXPECT-- +object(Test)#2 (0) { +} +object(Test)#3 (0) { +} +object(Test)#3 (0) { +} +NULL diff --git a/Zend/tests/gh10168_5.phpt b/Zend/tests/gh10168_5.phpt new file mode 100644 index 000000000000..62e239412b03 --- /dev/null +++ b/Zend/tests/gh10168_5.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): allocated assignment in destructor +--FILE-- + +--EXPECT-- +object(Test)#1 (0) { +} +object(Foo)#3 (0) { +} +object(Test)#2 (0) { +} +object(Foo)#1 (0) { +} diff --git a/Zend/tests/gh10168_6.phpt b/Zend/tests/gh10168_6.phpt new file mode 100644 index 000000000000..922bdd95c1fa --- /dev/null +++ b/Zend/tests/gh10168_6.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed prop without cache slot +--XFAIL-- +--FILE-- +storage = $this); + } else { + // Avoid cache slot, triggering write_property + var_dump($box->storage = $this); + } + } + + function __destruct() { + global $box; + $box->storage = null; + } +} +new Test(); +new Test(); + +?> +--EXPECT-- +object(Test)#2 (0) { +} +object(Test)#3 (0) { +} diff --git a/Zend/tests/gh10168_7.phpt b/Zend/tests/gh10168_7.phpt new file mode 100644 index 000000000000..d0ab5dfc2907 --- /dev/null +++ b/Zend/tests/gh10168_7.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed static prop by ref +--FILE-- + +--EXPECT-- +object(Test)#1 (0) { +} +object(Test)#2 (0) { +} +NULL +NULL diff --git a/Zend/tests/gh10168_8.phpt b/Zend/tests/gh10168_8.phpt new file mode 100644 index 000000000000..1d626badb1d0 --- /dev/null +++ b/Zend/tests/gh10168_8.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed prop +--FILE-- +storage = $this); + } + + function __destruct() { + global $box; + var_dump($box->storage); + $box->storage = null; + } +} +new Test(); +new Test(); + +?> +--EXPECT-- +object(Test)#2 (0) { +} +object(Test)#3 (0) { +} +object(Test)#3 (0) { +} +NULL diff --git a/Zend/tests/gh10168_9.phpt b/Zend/tests/gh10168_9.phpt new file mode 100644 index 000000000000..7b427681a8b2 --- /dev/null +++ b/Zend/tests/gh10168_9.phpt @@ -0,0 +1,34 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed prop +--FILE-- +value = $this); + } + + function __destruct() { + global $box; + unset($box->value); + } +} +new Test(); +new Test(); + +?> +--EXPECT-- +object(Test)#2 (0) { +} +object(Test)#3 (0) { +} diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 0d7025b68a64..2c11b402a169 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -546,21 +546,29 @@ static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr_ptr(int op_type, zno return get_zval_ptr_ptr(op_type, node, type); } -static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr) +static inline void zend_assign_to_variable_reference(zval *result_ptr, zval *variable_ptr, zval *value_ptr) { zend_reference *ref; if (EXPECTED(!Z_ISREF_P(value_ptr))) { ZVAL_NEW_REF(value_ptr, value_ptr); } else if (UNEXPECTED(variable_ptr == value_ptr)) { + if (UNEXPECTED(result_ptr)) { + ZVAL_COPY(result_ptr, value_ptr); + } return; } + zend_refcounted *garbage = Z_REFCOUNTED_P(variable_ptr) ? Z_COUNTED_P(variable_ptr) : NULL; + ref = Z_REF_P(value_ptr); GC_ADDREF(ref); - if (Z_REFCOUNTED_P(variable_ptr)) { - zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); + ZVAL_REF(variable_ptr, ref); + if (UNEXPECTED(result_ptr)) { + ZVAL_COPY(result_ptr, variable_ptr); + } + if (garbage != NULL) { if (GC_DELREF(garbage) == 0) { ZVAL_REF(variable_ptr, ref); rc_dtor_func(garbage); @@ -569,32 +577,41 @@ static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *v gc_check_possible_root(garbage); } } - ZVAL_REF(variable_ptr, ref); } -static zend_never_inline zval* zend_assign_to_typed_property_reference(zend_property_info *prop_info, zval *prop, zval *value_ptr EXECUTE_DATA_DC) +static zend_never_inline zval* zend_assign_to_typed_property_reference(zend_property_info *prop_info, zval *result_ptr, zval *prop, zval *value_ptr EXECUTE_DATA_DC) { if (!zend_verify_prop_assignable_by_ref(prop_info, value_ptr, EX_USES_STRICT_TYPES())) { + if (UNEXPECTED(result_ptr)) { + ZVAL_COPY(result_ptr, &EG(uninitialized_zval)); + } return &EG(uninitialized_zval); } if (Z_ISREF_P(prop)) { ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(prop), prop_info); } - zend_assign_to_variable_reference(prop, value_ptr); + zend_assign_to_variable_reference(result_ptr, prop, value_ptr); ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(prop), prop_info); return prop; } -static zend_never_inline ZEND_COLD zval *zend_wrong_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC) +static zend_never_inline ZEND_COLD zval *zend_wrong_assign_to_variable_reference(zval *result_ptr, zval *variable_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC) { zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { + if (UNEXPECTED(result_ptr)) { + ZVAL_COPY_VALUE(result_ptr, &EG(uninitialized_zval)); + } return &EG(uninitialized_zval); } /* Use IS_TMP_VAR instead of IS_VAR to avoid ISREF check */ Z_TRY_ADDREF_P(value_ptr); - return zend_assign_to_variable(variable_ptr, value_ptr, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + if (UNEXPECTED(result_ptr)) { + return zend_assign_to_two_variables(result_ptr, variable_ptr, value_ptr, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + return zend_assign_to_variable(variable_ptr, value_ptr, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } ZEND_API ZEND_COLD void ZEND_FASTCALL zend_cannot_pass_by_reference(uint32_t arg_num) @@ -1005,7 +1022,7 @@ ZEND_API bool zend_never_inline zend_verify_property_type(const zend_property_in return i_zend_verify_property_type(info, property, strict); } -static zend_never_inline zval* zend_assign_to_typed_prop(zend_property_info *info, zval *property_val, zval *value EXECUTE_DATA_DC) +static zend_never_inline zval* zend_assign_to_typed_prop(zend_property_info *info, zval *property_val, zval *value EXECUTE_DATA_DC OPLINE_DC) { zval tmp; @@ -1022,6 +1039,9 @@ static zend_never_inline zval* zend_assign_to_typed_prop(zend_property_info *inf return &EG(uninitialized_zval); } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + return zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, &tmp, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } return zend_assign_to_variable(property_val, &tmp, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } @@ -3248,14 +3268,15 @@ static zend_always_inline void zend_assign_to_property_reference(zval *container zend_fetch_property_address(variable_ptr, container, container_op_type, prop_ptr, prop_op_type, cache_addr, BP_VAR_W, 0, 0 OPLINE_CC EXECUTE_DATA_CC); + zval *result_ptr = UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL; + if (EXPECTED(Z_TYPE_P(variable_ptr) == IS_INDIRECT)) { variable_ptr = Z_INDIRECT_P(variable_ptr); if (/*OP_DATA_TYPE == IS_VAR &&*/ (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { - variable_ptr = zend_wrong_assign_to_variable_reference( - variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); + variable_ptr = zend_wrong_assign_to_variable_reference(result_ptr, variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); } else { zend_property_info *prop_info = NULL; @@ -3267,21 +3288,21 @@ static zend_always_inline void zend_assign_to_property_reference(zval *container } if (UNEXPECTED(prop_info)) { - variable_ptr = zend_assign_to_typed_property_reference(prop_info, variable_ptr, value_ptr EXECUTE_DATA_CC); + variable_ptr = zend_assign_to_typed_property_reference(prop_info, result_ptr, variable_ptr, value_ptr EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); + zend_assign_to_variable_reference(result_ptr, variable_ptr, value_ptr); } } } else if (Z_ISERROR_P(variable_ptr)) { - variable_ptr = &EG(uninitialized_zval); + if (result_ptr) { + ZVAL_COPY(result_ptr, &EG(uninitialized_zval)); + } } else { zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); zval_ptr_dtor(&variable); - variable_ptr = &EG(uninitialized_zval); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + if (result_ptr) { + ZVAL_COPY(result_ptr, &EG(uninitialized_zval)); + } } } @@ -3602,13 +3623,21 @@ ZEND_API zval* zend_assign_to_typed_ref_and_result(zval *variable_ptr, zval *ori ret = zend_verify_ref_assignable_zval(Z_REF_P(variable_ptr), &value, strict); variable_ptr = Z_REFVAL_P(variable_ptr); if (EXPECTED(ret)) { - i_zval_ptr_dtor_noref(variable_ptr); + // The destructor must run after the variable has already been reassigned + // Otherwise, assigning to the variable again can cause a double free + // Thus we need to store the old value in a temporary slot + zval garbage; + ZVAL_COPY_VALUE(&garbage, variable_ptr); ZVAL_COPY_VALUE(variable_ptr, &value); + i_zval_ptr_dtor_noref(&garbage); + if (result_variable_ptr) { + ZVAL_COPY_DEREF(result_variable_ptr, &value); + } } else { zval_ptr_dtor_nogc(&value); - } - if (result_variable_ptr) { - ZVAL_COPY(result_variable_ptr, variable_ptr); + if (result_variable_ptr) { + ZVAL_UNDEF(result_variable_ptr); + } } if (value_type & (IS_VAR|IS_TMP_VAR)) { if (UNEXPECTED(ref)) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 1785fcfe2a14..42fcfd54c22f 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2410,13 +2410,15 @@ ZEND_VM_C_LABEL(assign_object): zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - ZEND_VM_C_GOTO(free_and_exit_assign_obj); + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + FREE_OP_DATA(); + ZEND_VM_C_GOTO(exit_assign_obj); } else { ZEND_VM_C_LABEL(fast_assign_obj): - value = zend_assign_to_variable(property_val, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); } ZEND_VM_C_GOTO(exit_assign_obj); } @@ -2522,14 +2524,14 @@ ZEND_VM_HANDLER(25, ZEND_ASSIGN_STATIC_PROP, ANY, ANY, CACHE_SLOT, SPEC(OP_DATA= value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC OPLINE_CC); FREE_OP_DATA(); } else { - value = zend_assign_to_variable(prop, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), prop, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(prop, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); + } } /* assign_static_prop has two opcodes! */ @@ -2725,19 +2727,18 @@ ZEND_VM_HANDLER(30, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC) UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); - variable_ptr = &EG(uninitialized_zval); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), &EG(uninitialized_zval)); + } } else if (OP2_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { - variable_ptr = zend_wrong_assign_to_variable_reference( + zend_wrong_assign_to_variable_reference( + UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + zend_assign_to_variable_reference(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, variable_ptr, value_ptr); } FREE_OP2(); @@ -2785,7 +2786,7 @@ ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CA ZEND_VM_HANDLER(33, ZEND_ASSIGN_STATIC_PROP_REF, ANY, ANY, CACHE_SLOT|SRC) { USE_OPLINE - zval *prop, *value_ptr; + zval *prop, *value_ptr, *result_ptr; zend_property_info *prop_info; SAVE_OPLINE(); @@ -2797,19 +2798,16 @@ ZEND_VM_HANDLER(33, ZEND_ASSIGN_STATIC_PROP_REF, ANY, ANY, CACHE_SLOT|SRC) } value_ptr = GET_OP_DATA_ZVAL_PTR_PTR(BP_VAR_W); + result_ptr = UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL; if (OP_DATA_TYPE == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { - if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(prop, value_ptr OPLINE_CC EXECUTE_DATA_CC))) { + if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(result_ptr, prop, value_ptr OPLINE_CC EXECUTE_DATA_CC))) { prop = &EG(uninitialized_zval); } } else if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - prop = zend_assign_to_typed_property_reference(prop_info, prop, value_ptr EXECUTE_DATA_CC); + prop = zend_assign_to_typed_property_reference(prop_info, result_ptr, prop, value_ptr EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(prop, value_ptr); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), prop); + zend_assign_to_variable_reference(result_ptr, prop, value_ptr); } FREE_OP_DATA(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 00cf2461b91c..8a21ff319a76 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -939,14 +939,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT value = RT_CONSTANT((opline+1), (opline+1)->op1); if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC OPLINE_CC); } else { - value = zend_assign_to_variable(prop, value, IS_CONST, EX_USES_STRICT_TYPES()); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), prop, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(prop, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } /* assign_static_prop has two opcodes! */ @@ -970,14 +970,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC OPLINE_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else { - value = zend_assign_to_variable(prop, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), prop, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(prop, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } /* assign_static_prop has two opcodes! */ @@ -1001,14 +1001,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC OPLINE_CC); zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); } else { - value = zend_assign_to_variable(prop, value, IS_VAR, EX_USES_STRICT_TYPES()); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), prop, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(prop, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } /* assign_static_prop has two opcodes! */ @@ -1032,14 +1032,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); + value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC OPLINE_CC); } else { - value = zend_assign_to_variable(prop, value, IS_CV, EX_USES_STRICT_TYPES()); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), prop, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(prop, value, IS_CV, EX_USES_STRICT_TYPES()); + } } /* assign_static_prop has two opcodes! */ @@ -1049,7 +1049,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_SPEC_OP_DAT static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *prop, *value_ptr; + zval *prop, *value_ptr, *result_ptr; zend_property_info *prop_info; SAVE_OPLINE(); @@ -1061,19 +1061,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_STATIC_PROP_REF_SPEC_HA } value_ptr = get_zval_ptr_ptr((opline+1)->op1_type, (opline+1)->op1, BP_VAR_W); + result_ptr = UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL; if ((opline+1)->op1_type == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { - if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(prop, value_ptr OPLINE_CC EXECUTE_DATA_CC))) { + if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(result_ptr, prop, value_ptr OPLINE_CC EXECUTE_DATA_CC))) { prop = &EG(uninitialized_zval); } } else if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { - prop = zend_assign_to_typed_property_reference(prop_info, prop, value_ptr EXECUTE_DATA_CC); + prop = zend_assign_to_typed_property_reference(prop_info, result_ptr, prop, value_ptr EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(prop, value_ptr); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), prop); + zend_assign_to_variable_reference(result_ptr, prop, value_ptr); } FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); @@ -23288,13 +23285,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -23418,13 +23417,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -23548,13 +23549,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -23678,13 +23681,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -26164,13 +26169,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -26294,13 +26301,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -26424,13 +26433,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -26554,13 +26565,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -28035,19 +28048,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); - variable_ptr = &EG(uninitialized_zval); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), &EG(uninitialized_zval)); + } } else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { - variable_ptr = zend_wrong_assign_to_variable_reference( + zend_wrong_assign_to_variable_reference( + UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + zend_assign_to_variable_reference(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, variable_ptr, value_ptr); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -30407,13 +30419,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -30537,13 +30551,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -30667,13 +30683,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -30797,13 +30815,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -31560,19 +31580,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); - variable_ptr = &EG(uninitialized_zval); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), &EG(uninitialized_zval)); + } } else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { - variable_ptr = zend_wrong_assign_to_variable_reference( + zend_wrong_assign_to_variable_reference( + UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + zend_assign_to_variable_reference(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, variable_ptr, value_ptr); } zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -33005,13 +33024,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -33135,13 +33156,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -33265,13 +33288,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -33395,13 +33420,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_O zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -35023,13 +35050,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -35153,13 +35182,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -35283,13 +35314,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -35413,13 +35446,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -37497,13 +37532,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -37627,13 +37664,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -37757,13 +37796,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -37887,13 +37928,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -41674,13 +41717,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -41804,13 +41849,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -41934,13 +41981,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -42064,13 +42113,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DA zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -45481,13 +45532,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -45611,13 +45664,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -45741,13 +45796,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -45871,13 +45928,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_D zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -47627,19 +47686,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); - variable_ptr = &EG(uninitialized_zval); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), &EG(uninitialized_zval)); + } } else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { - variable_ptr = zend_wrong_assign_to_variable_reference( + zend_wrong_assign_to_variable_reference( + UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + zend_assign_to_variable_reference(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, variable_ptr, value_ptr); } zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -50845,13 +50903,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CONST, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -50975,13 +51035,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -51105,13 +51167,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_VAR, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -51235,13 +51299,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_ zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); if (UNEXPECTED(prop_info != NULL)) { - value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); - goto free_and_exit_assign_obj; + value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC OPLINE_CC); + + goto exit_assign_obj; } else { fast_assign_obj: - value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + value = zend_assign_to_two_variables(EX_VAR(opline->result.var), property_val, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + value = zend_assign_to_variable(property_val, value, IS_CV, EX_USES_STRICT_TYPES()); } goto exit_assign_obj; } @@ -51996,19 +52062,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER( UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); - variable_ptr = &EG(uninitialized_zval); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), &EG(uninitialized_zval)); + } } else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && UNEXPECTED(!Z_ISREF_P(value_ptr))) { - variable_ptr = zend_wrong_assign_to_variable_reference( + zend_wrong_assign_to_variable_reference( + UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); - } - - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + zend_assign_to_variable_reference(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, variable_ptr, value_ptr); }