]> granicus.if.org Git - php/commitdiff
Use COPY_DEREF instead of COPY_UNREF
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 14 Jun 2018 21:34:26 +0000 (23:34 +0200)
committerJoe Watkins <krakjoe@php.net>
Mon, 25 Jun 2018 09:23:59 +0000 (11:23 +0200)
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.

Zend/tests/bug72543_5.phpt
Zend/zend_execute.c
Zend/zend_types.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/opcache/Optimizer/zend_inference.c

index 66b3b75f2a53ba91afe8ee7cffc7f724ac40bbda..dc2fcdafe23296605351fde1f07527258cb7c58d 100644 (file)
@@ -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)
index 9a170edd3daeb682dfcbe9bd525298a6d298aa3d..86590383b021135cb33f7e5fb968495f2fb88b80 100644 (file)
@@ -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);
index 984c93b9f78052a7e7d1e6f01c662a01450abaa3..8e6a21d052b97dbde6c61a56d95621425ed9b2b3 100644 (file)
@@ -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);                                        \
                                }                                                                               \
index 42b50bccfaaa32a2e3e36bce62f15cb51442ccc9..0a45b09ab954e4c438a2bf5061f18b28575f0a8f 100644 (file)
@@ -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();
index fb96a92d8a04d4423afe1d535a6fc5f77d2cb996..b5bf42ec3bb028d8610a4bcff58ec37adbca0993 100644 (file)
@@ -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);
index 9298f983e30b55be6764bafd097f14d454521313..25b8ecd6b2713980f0860da2a350e2a533e981c2 100644 (file)
@@ -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);
                        }