From 71ddede5655fe654002ae18af6a18e033f717287 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 6 Feb 2023 21:59:07 +0100 Subject: [PATCH] Fix GH-10168: heap-buffer-overflow at zval_undefined_cv The problem is that we're using the variable_ptr in the opcode handler *after* it has already been destroyed. The solution is to create a specialised version of zend_assign_to_variable which takes in two destination zval pointers. Closes GH-10524 --- NEWS | 2 + Zend/tests/gh10168_1.phpt | 32 +++ Zend/tests/gh10168_2.phpt | 32 +++ Zend/tests/gh10168_3.phpt | 29 +++ Zend/zend_execute.c | 10 +- Zend/zend_execute.h | 54 +++- Zend/zend_vm_def.h | 20 +- Zend/zend_vm_execute.h | 504 +++++++++++++++++++++++++------------- 8 files changed, 488 insertions(+), 195 deletions(-) create mode 100644 Zend/tests/gh10168_1.phpt create mode 100644 Zend/tests/gh10168_2.phpt create mode 100644 Zend/tests/gh10168_3.phpt diff --git a/NEWS b/NEWS index bb3d77ca491..ce886d1638c 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS Generator emits an unavoidable fatal error or crashes). (Arnaud) . Fixed bug GH-10437 (Segfault/assertion when using fibers in shutdown function after bailout). (trowski) + . Fixed bug GH-10168: use-after-free when utilizing assigned object freed + during assignment. (nielsdos) - Date: . Fix GH-10447 ('p' format specifier does not yield 'Z' for 00:00). (Derick) diff --git a/Zend/tests/gh10168_1.phpt b/Zend/tests/gh10168_1.phpt new file mode 100644 index 00000000000..6433453ed24 --- /dev/null +++ b/Zend/tests/gh10168_1.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): array variation +--FILE-- + 0; + var_dump(self::$instances); + } + + function __destruct() { + unset(self::$instances[NULL]); + } +} +new Test(); +new Test(); + +?> +--EXPECTF-- +Notice: Object of class Test could not be converted to int in %s on line %d +array(1) { + [""]=> + object(Test)#1 (0) { + } +} + +Notice: Object of class Test could not be converted to int in %s on line %d +array(0) { +} diff --git a/Zend/tests/gh10168_2.phpt b/Zend/tests/gh10168_2.phpt new file mode 100644 index 00000000000..abab8b72f1c --- /dev/null +++ b/Zend/tests/gh10168_2.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign global variation +--FILE-- + 0; + // Destructor called after comparison, so a will be NULL + var_dump($GLOBALS['a']); + } + + function __destruct() { + unset($GLOBALS['a']); + } +} +new Test(); +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 + +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 new file mode 100644 index 00000000000..fb8729c9966 --- /dev/null +++ b/Zend/tests/gh10168_3.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-10168 (heap-buffer-overflow at zval_undefined_cv): assign typed prop +--FILE-- + +--EXPECTF-- +object(Test)#1 (0) { +} +object(Test)#2 (0) { +} diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 922b45c42ba..49af6fc7695 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3562,7 +3562,7 @@ static zend_always_inline void i_zval_ptr_dtor_noref(zval *zval_ptr) { } } -ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict) +ZEND_API zval* zend_assign_to_typed_ref_and_result(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict, zval *result_variable_ptr) { bool ret; zval value; @@ -3582,6 +3582,9 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ze } else { zval_ptr_dtor_nogc(&value); } + if (result_variable_ptr) { + ZVAL_COPY(result_variable_ptr, variable_ptr); + } if (value_type & (IS_VAR|IS_TMP_VAR)) { if (UNEXPECTED(ref)) { if (UNEXPECTED(GC_DELREF(ref) == 0)) { @@ -3595,6 +3598,11 @@ ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, ze return variable_ptr; } +ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict) +{ + return zend_assign_to_typed_ref_and_result(variable_ptr, orig_value, value_type, strict, NULL); +} + ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_property_info *prop_info, zval *orig_val, bool strict) { zval *val = orig_val; if (Z_ISREF_P(val) && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(val))) { diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 3e61967cb2b..1091b1ebe65 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -108,6 +108,7 @@ ZEND_API bool zend_verify_internal_return_type(zend_function *zf, zval *ret); ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_list *source_list, zend_property_info *prop); ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_list *source_list, zend_property_info *prop); +ZEND_API zval* zend_assign_to_typed_ref_and_result(zval *variable_ptr, zval *orig_value, zend_uchar value_type, bool strict, zval *result_variable_ptr); ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *value, zend_uchar value_type, bool strict); static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type) @@ -137,12 +138,22 @@ static zend_always_inline void zend_copy_to_variable(zval *variable_ptr, zval *v } } +static zend_always_inline void zend_handle_garbage_from_variable_assignment(zend_refcounted *garbage) +{ + if (GC_DELREF(garbage) == 0) { + rc_dtor_func(garbage); + } else { /* we need to split */ + /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */ + if (UNEXPECTED(GC_MAY_LEAK(garbage))) { + gc_possible_root(garbage); + } + } +} + static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type, bool strict) { do { if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { - zend_refcounted *garbage; - if (Z_ISREF_P(variable_ptr)) { if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) { return zend_assign_to_typed_ref(variable_ptr, value, value_type, strict); @@ -153,16 +164,9 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval break; } } - garbage = Z_COUNTED_P(variable_ptr); + zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); zend_copy_to_variable(variable_ptr, value, value_type); - if (GC_DELREF(garbage) == 0) { - rc_dtor_func(garbage); - } else { /* we need to split */ - /* optimized version of GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr) */ - if (UNEXPECTED(GC_MAY_LEAK(garbage))) { - gc_possible_root(garbage); - } - } + zend_handle_garbage_from_variable_assignment(garbage); return variable_ptr; } } while (0); @@ -171,6 +175,34 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval return variable_ptr; } +static zend_always_inline zval* zend_assign_to_two_variables(zval *result_variable_ptr, zval *variable_ptr, zval *value, zend_uchar value_type, bool strict) +{ + do { + if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { + if (Z_ISREF_P(variable_ptr)) { + if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(variable_ptr)))) { + variable_ptr = zend_assign_to_typed_ref_and_result(variable_ptr, value, value_type, strict, result_variable_ptr); + return variable_ptr; + } + + variable_ptr = Z_REFVAL_P(variable_ptr); + if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) { + break; + } + } + zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); + zend_copy_to_variable(variable_ptr, value, value_type); + ZVAL_COPY(result_variable_ptr, variable_ptr); + zend_handle_garbage_from_variable_assignment(garbage); + return variable_ptr; + } + } while (0); + + zend_copy_to_variable(variable_ptr, value, value_type); + ZVAL_COPY(result_variable_ptr, variable_ptr); + return variable_ptr; +} + ZEND_API zend_result ZEND_FASTCALL zval_update_constant(zval *pp); ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *pp, zend_class_entry *scope); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 4845a92b95a..09d7b95896e 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2577,6 +2577,9 @@ ZEND_VM_C_LABEL(try_assign_dim_array): Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP2_TYPE == IS_CONST) { @@ -2588,10 +2591,11 @@ ZEND_VM_C_LABEL(try_assign_dim_array): ZEND_VM_C_GOTO(assign_dim_error); } value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -2685,12 +2689,14 @@ ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL)) value = GET_OP2_ZVAL_PTR(BP_VAR_R); variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); - value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); } + FREE_OP1_VAR_PTR(); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a5a5eabf2b0..6f1b9b49f72 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -23464,6 +23464,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -23475,10 +23478,11 @@ try_assign_dim_array: goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -23612,6 +23616,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -23623,10 +23630,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -23761,6 +23769,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -23772,10 +23783,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -23910,6 +23922,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -23921,10 +23936,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -24017,12 +24033,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U value = RT_CONSTANT(opline, opline->op2); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -24037,12 +24055,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_U value = RT_CONSTANT(opline, opline->op2); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -26163,6 +26183,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -26174,10 +26197,11 @@ try_assign_dim_array: goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -26311,6 +26335,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -26322,10 +26349,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -26460,6 +26488,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -26471,10 +26502,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -26609,6 +26641,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -26620,10 +26655,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -27346,12 +27382,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNU value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27366,12 +27404,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USE value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27430,12 +27470,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNU value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27450,12 +27492,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USE value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -27694,6 +27738,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -27705,10 +27752,11 @@ try_assign_dim_array: goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -27842,6 +27890,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -27853,10 +27904,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -27991,6 +28043,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -28002,10 +28057,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -28140,6 +28196,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -28151,10 +28210,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30370,6 +30430,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -30381,10 +30444,11 @@ try_assign_dim_array: goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30518,6 +30582,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -30529,10 +30596,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30667,6 +30735,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -30678,10 +30749,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30816,6 +30888,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -30827,10 +30902,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -30923,12 +30999,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUS value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -30943,12 +31021,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -41421,6 +41501,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -41432,10 +41515,11 @@ try_assign_dim_array: goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -41569,6 +41653,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -41580,10 +41667,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -41718,6 +41806,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -41729,10 +41820,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -41867,6 +41959,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = RT_CONSTANT(opline, opline->op2); if (IS_CONST == IS_CONST) { @@ -41878,10 +41973,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -41974,12 +42070,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UN value = RT_CONSTANT(opline, opline->op2); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -41994,12 +42091,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_US value = RT_CONSTANT(opline, opline->op2); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -45199,6 +45297,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -45210,10 +45311,11 @@ try_assign_dim_array: goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -45347,6 +45449,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -45358,10 +45463,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -45496,6 +45602,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -45507,10 +45616,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -45645,6 +45755,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { @@ -45656,10 +45769,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -46670,12 +46784,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUS value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -46690,12 +46805,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED value = _get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -46740,12 +46856,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUS value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -46760,12 +46877,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED value = _get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -47177,6 +47295,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -47188,10 +47309,11 @@ try_assign_dim_array: goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -47325,6 +47447,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -47336,10 +47461,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -47474,6 +47600,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -47485,10 +47614,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -47623,6 +47753,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = NULL; if (IS_UNUSED == IS_CONST) { @@ -47634,10 +47767,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -50514,6 +50648,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -50525,10 +50662,11 @@ try_assign_dim_array: goto assign_dim_error; } value = RT_CONSTANT((opline+1), (opline+1)->op1); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CONST, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -50662,6 +50800,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -50673,10 +50814,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -50811,6 +50953,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -50822,10 +50967,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_VAR, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -50960,6 +51106,9 @@ try_assign_dim_array: Z_ADDREF_P(value); } } + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } } else { dim = EX_VAR(opline->op2.var); if (IS_CV == IS_CONST) { @@ -50971,10 +51120,11 @@ try_assign_dim_array: goto assign_dim_error; } value = _get_zval_ptr_cv_BP_VAR_R((opline+1)->op1.var EXECUTE_DATA_CC); - value = zend_assign_to_variable(variable_ptr, 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))) { + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } } } else { if (EXPECTED(Z_ISREF_P(object_ptr))) { @@ -51067,12 +51217,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSE value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(0)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -51087,12 +51238,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_ value = _get_zval_ptr_cv_BP_VAR_R(opline->op2.var EXECUTE_DATA_CC); variable_ptr = EX_VAR(opline->op1.var); - value = zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); if (UNEXPECTED(1)) { - ZVAL_COPY(EX_VAR(opline->result.var), value); + zend_assign_to_two_variables(EX_VAR(opline->result.var), variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); + } else { + zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES()); } - /* zend_assign_to_variable() always takes care of op2, never free it! */ + /* zend_assign_to_(two_)variable(s)() always takes care of op2, never free it! */ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); }