From: Nikita Popov Date: Thu, 14 Jun 2018 21:34:26 +0000 (+0200) Subject: Use COPY_DEREF instead of COPY_UNREF X-Git-Tag: php-7.3.0alpha3~80 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=61d00a6cf3d5e8471cc05bdb686b1f399c0f15a4;p=php Use COPY_DEREF instead of COPY_UNREF This fixes the behavior when the storage location of the fetch is modified before the operand is dereferenced by the using VM opcode. Furthermore it elimiates references as a possible return value from *_R opcodes, which will give us more opportunities for inferences, in particular in regard to typed properties. --- diff --git a/Zend/tests/bug72543_5.phpt b/Zend/tests/bug72543_5.phpt index 66b3b75f2a..dc2fcdafe2 100644 --- a/Zend/tests/bug72543_5.phpt +++ b/Zend/tests/bug72543_5.phpt @@ -5,6 +5,13 @@ Bug #72543.5 (different references behavior comparing to PHP 5) $arr = [1]; $ref =& $arr[0]; var_dump($arr[0] + ($arr[0] = 2)); + +$obj = new stdClass; +$obj->prop = 1; +$ref =& $obj->prop; +var_dump($obj->prop + ($obj->prop = 2)); + ?> --EXPECT-- -int(4) +int(3) +int(3) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 9a170edd3d..86590383b0 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2033,7 +2033,9 @@ try_string_offset: ZEND_ASSERT(result != NULL); if (retval) { if (result != retval) { - ZVAL_COPY(result, retval); + ZVAL_COPY_DEREF(result, retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(result); } } else { ZVAL_NULL(result); diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 984c93b9f7..8e6a21d052 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -1123,12 +1123,11 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) { efree_size(ref, sizeof(zend_reference)); \ } while (0) -#define ZVAL_COPY_UNREF(z, v) do { \ +#define ZVAL_COPY_DEREF(z, v) do { \ zval *_z3 = (v); \ if (Z_OPT_REFCOUNTED_P(_z3)) { \ - if (UNEXPECTED(Z_OPT_ISREF_P(_z3)) \ - && UNEXPECTED(Z_REFCOUNT_P(_z3) == 1)) { \ - ZVAL_UNREF(_z3); \ + if (UNEXPECTED(Z_OPT_ISREF_P(_z3))) { \ + _z3 = Z_REFVAL_P(_z3); \ if (Z_OPT_REFCOUNTED_P(_z3)) { \ Z_ADDREF_P(_z3); \ } \ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 42b50bccfa..0a45b09ab9 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1454,7 +1454,7 @@ ZEND_VM_C_LABEL(fetch_this): ZEND_ASSERT(retval != NULL); if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -1580,7 +1580,7 @@ ZEND_VM_HELPER(zend_fetch_static_prop_helper, CONST|TMPVAR|CV, UNUSED|CONST|VAR, } if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -1634,7 +1634,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMP ZEND_VM_C_LABEL(fetch_dim_r_array): value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, OP2_TYPE, BP_VAR_R EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); - ZVAL_COPY_UNREF(result, value); + ZVAL_COPY_DEREF(result, value); } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -1809,7 +1809,7 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { retval = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } else if (EXPECTED(zobj->properties != NULL)) { @@ -1824,7 +1824,7 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && EXPECTED(p->key != NULL) && EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), &p->val); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val); break; } } @@ -1834,7 +1834,7 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } @@ -1851,7 +1851,9 @@ ZEND_VM_C_LABEL(fetch_obj_r_no_object): retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } } } while (0); @@ -8654,7 +8656,7 @@ ZEND_VM_C_LABEL(fetch_dim_r_index_array): } ht = Z_ARRVAL_P(container); ZEND_HASH_INDEX_FIND(ht, offset, value, ZEND_VM_C_LABEL(fetch_dim_r_index_undef)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); FREE_OP1(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index fb96a92d8a..b5bf42ec3b 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4607,7 +4607,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_ } if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -4661,7 +4661,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_ fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); - ZVAL_COPY_UNREF(result, value); + ZVAL_COPY_DEREF(result, value); } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -4761,7 +4761,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { retval = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } else if (EXPECTED(zobj->properties != NULL)) { @@ -4776,7 +4776,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && EXPECTED(p->key != NULL) && EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), &p->val); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val); break; } } @@ -4786,7 +4786,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } @@ -4803,7 +4803,9 @@ fetch_obj_r_no_object: retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } } } while (0); @@ -6321,7 +6323,7 @@ fetch_dim_r_index_array: } ht = Z_ARRVAL_P(container); ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); if (IS_CONST & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); @@ -6751,7 +6753,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_ fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); - ZVAL_COPY_UNREF(result, value); + ZVAL_COPY_DEREF(result, value); } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -6851,7 +6853,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { retval = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } else if (EXPECTED(zobj->properties != NULL)) { @@ -6866,7 +6868,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && EXPECTED(p->key != NULL) && EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), &p->val); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val); break; } } @@ -6876,7 +6878,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } @@ -6893,7 +6895,9 @@ fetch_obj_r_no_object: retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } } } while (0); @@ -7941,7 +7945,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_ } if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -8327,7 +8331,7 @@ fetch_this: ZEND_ASSERT(retval != NULL); if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -8452,7 +8456,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_ } if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -9826,7 +9830,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HAND fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); - ZVAL_COPY_UNREF(result, value); + ZVAL_COPY_DEREF(result, value); } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -9926,7 +9930,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { retval = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } else if (EXPECTED(zobj->properties != NULL)) { @@ -9941,7 +9945,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && EXPECTED(p->key != NULL) && EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), &p->val); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val); break; } } @@ -9951,7 +9955,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_ if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } @@ -9968,7 +9972,9 @@ fetch_obj_r_no_object: retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } } } while (0); @@ -13489,7 +13495,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_ } if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -13543,7 +13549,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_ fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); - ZVAL_COPY_UNREF(result, value); + ZVAL_COPY_DEREF(result, value); } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -13628,7 +13634,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { retval = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } else if (EXPECTED(zobj->properties != NULL)) { @@ -13643,7 +13649,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && EXPECTED(p->key != NULL) && EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), &p->val); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val); break; } } @@ -13653,7 +13659,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CONST_ if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } @@ -13670,7 +13676,9 @@ fetch_obj_r_no_object: retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } } } while (0); @@ -14394,7 +14402,7 @@ fetch_dim_r_index_array: } ht = Z_ARRVAL_P(container); ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); zval_ptr_dtor_nogc(free_op1); @@ -14444,7 +14452,7 @@ fetch_dim_r_index_array: } ht = Z_ARRVAL_P(container); ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); if ((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); zval_ptr_dtor_nogc(free_op1); @@ -15132,7 +15140,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); - ZVAL_COPY_UNREF(result, value); + ZVAL_COPY_DEREF(result, value); } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -15217,7 +15225,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { retval = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } else if (EXPECTED(zobj->properties != NULL)) { @@ -15232,7 +15240,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && EXPECTED(p->key != NULL) && EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), &p->val); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val); break; } } @@ -15242,7 +15250,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_TMPVAR if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } @@ -15259,7 +15267,9 @@ fetch_obj_r_no_object: retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } } } while (0); @@ -15873,7 +15883,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_ } if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -16172,7 +16182,7 @@ fetch_this: ZEND_ASSERT(retval != NULL); if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -16298,7 +16308,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_ } if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -16998,7 +17008,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HAN fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); - ZVAL_COPY_UNREF(result, value); + ZVAL_COPY_DEREF(result, value); } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -17083,7 +17093,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { retval = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } else if (EXPECTED(zobj->properties != NULL)) { @@ -17098,7 +17108,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && EXPECTED(p->key != NULL) && EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), &p->val); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val); break; } } @@ -17108,7 +17118,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMPVAR_CV_HAN if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } @@ -17125,7 +17135,9 @@ fetch_obj_r_no_object: retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } } } while (0); @@ -30652,7 +30664,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_U if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { retval = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } else if (EXPECTED(zobj->properties != NULL)) { @@ -30667,7 +30679,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_U (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && EXPECTED(p->key != NULL) && EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), &p->val); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val); break; } } @@ -30677,7 +30689,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_U if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } @@ -30694,7 +30706,9 @@ fetch_obj_r_no_object: retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } } } while (0); @@ -32395,7 +32409,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { retval = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } else if (EXPECTED(zobj->properties != NULL)) { @@ -32410,7 +32424,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && EXPECTED(p->key != NULL) && EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), &p->val); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val); break; } } @@ -32420,7 +32434,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } @@ -32437,7 +32451,9 @@ fetch_obj_r_no_object: retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } } } while (0); @@ -34766,7 +34782,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { retval = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } else if (EXPECTED(zobj->properties != NULL)) { @@ -34781,7 +34797,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && EXPECTED(p->key != NULL) && EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), &p->val); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val); break; } } @@ -34791,7 +34807,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } @@ -34808,7 +34824,9 @@ fetch_obj_r_no_object: retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } } } while (0); @@ -39028,7 +39046,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_ } if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -39082,7 +39100,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HAND fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CONST, BP_VAR_R EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); - ZVAL_COPY_UNREF(result, value); + ZVAL_COPY_DEREF(result, value); } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -39233,7 +39251,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_C if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { retval = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } else if (EXPECTED(zobj->properties != NULL)) { @@ -39248,7 +39266,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_C (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && EXPECTED(p->key != NULL) && EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), &p->val); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val); break; } } @@ -39258,7 +39276,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_C if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } @@ -39275,7 +39293,9 @@ fetch_obj_r_no_object: retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } } } while (0); @@ -41489,7 +41509,7 @@ fetch_dim_r_index_array: } ht = Z_ARRVAL_P(container); ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); @@ -41539,7 +41559,7 @@ fetch_dim_r_index_array: } ht = Z_ARRVAL_P(container); ZEND_HASH_INDEX_FIND(ht, offset, value, fetch_dim_r_index_undef); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), value); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); if (IS_CV & (IS_TMP_VAR|IS_VAR)) { SAVE_OPLINE(); @@ -42807,7 +42827,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HAN fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_R EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); - ZVAL_COPY_UNREF(result, value); + ZVAL_COPY_DEREF(result, value); } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -42958,7 +42978,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { retval = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } else if (EXPECTED(zobj->properties != NULL)) { @@ -42973,7 +42993,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && EXPECTED(p->key != NULL) && EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), &p->val); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val); break; } } @@ -42983,7 +43003,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } @@ -43000,7 +43020,9 @@ fetch_obj_r_no_object: retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } } } while (0); @@ -45005,7 +45027,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_ } if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -45715,7 +45737,7 @@ fetch_this: ZEND_ASSERT(retval != NULL); if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -45840,7 +45862,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_ } if (type == BP_VAR_R || type == BP_VAR_IS) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); } else { ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); } @@ -48321,7 +48343,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER fetch_dim_r_array: value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, IS_CV, BP_VAR_R EXECUTE_DATA_CC); result = EX_VAR(opline->result.var); - ZVAL_COPY_UNREF(result, value); + ZVAL_COPY_DEREF(result, value); } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { container = Z_REFVAL_P(container); if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { @@ -48472,7 +48494,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { retval = OBJ_PROP(zobj, prop_offset); if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } else if (EXPECTED(zobj->properties != NULL)) { @@ -48487,7 +48509,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && EXPECTED(p->key != NULL) && EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), &p->val); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val); break; } } @@ -48497,7 +48519,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER if (EXPECTED(retval)) { uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); break; } } @@ -48514,7 +48536,9 @@ fetch_obj_r_no_object: retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); if (retval != EX_VAR(opline->result.var)) { - ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval); + ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); + } else if (UNEXPECTED(Z_ISREF_P(retval))) { + zend_unwrap_reference(retval); } } } while (0); diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index 9298f983e3..25b8ecd6b2 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -3326,13 +3326,10 @@ static int zend_update_type_info(const zend_op_array *op_array, } if (ssa_ops[i].result_def >= 0) { tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; - if (opline->opcode != ZEND_FETCH_OBJ_R && opline->opcode != ZEND_FETCH_OBJ_IS) { - tmp |= MAY_BE_ERROR; - } - if (opline->result_type == IS_TMP_VAR) { + if (opline->opcode == ZEND_FETCH_OBJ_R || opline->opcode == ZEND_FETCH_OBJ_IS) { tmp |= MAY_BE_RC1 | MAY_BE_RCN; } else { - tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN; + tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ERROR; } UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def); }