]> granicus.if.org Git - php/commitdiff
Fixed uninitialized result of PRE_INC/PRE_DEC in case of exception.
authorDmitry Stogov <dmitry@zend.com>
Tue, 15 Jan 2019 15:03:46 +0000 (18:03 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 15 Jan 2019 15:03:46 +0000 (18:03 +0300)
Separated increment/decrement of typed reference into helper.

Zend/tests/type_declarations/typed_properties_104.phpt [new file with mode: 0644]
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/type_declarations/typed_properties_104.phpt b/Zend/tests/type_declarations/typed_properties_104.phpt
new file mode 100644 (file)
index 0000000..e7d69e3
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Uninitialized result of PRE_INC/PRE_DEC in case of exception
+--FILE--
+<?php
+declare(strict_types=1);
+$o = new class {
+       public string $a = "123";
+};
+$x = & $o->a;
+try {
+       $ret = ++$x + 5;
+} catch (TypeError $e) {
+}
+?>
+OK
+--EXPECT--
+OK
index fbc50bd2f65c6e11f2b68e15f00e54844c09a350..3dbcff34b6ad0066f8d95ff58b1910c5f2926168 100644 (file)
@@ -1613,6 +1613,34 @@ static ZEND_COLD void zend_throw_incdec_prop_error(zend_property_info *prop, zen
                inc ? "max" : "min");
 }
 
+static void zend_incdec_typed_ref(zend_reference *ref, zval *copy, int inc EXECUTE_DATA_DC)
+{
+       zval tmp;
+       zval *var_ptr = &ref->val;
+
+       if (!copy) {
+               copy = &tmp;
+       }
+
+       ZVAL_COPY(copy, var_ptr);
+
+       if (inc) {
+               increment_function(var_ptr);
+       } else {
+               decrement_function(var_ptr);
+       }
+
+       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE_P(copy) == IS_LONG) {
+               zend_throw_incdec_ref_error(ref, inc);
+               ZVAL_COPY_VALUE(var_ptr, copy);
+       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
+               zval_ptr_dtor(var_ptr);
+               ZVAL_COPY_VALUE(var_ptr, copy);
+       } else if (copy == &tmp) {
+               zval_ptr_dtor(&tmp);
+       }
+}
+
 static void zend_pre_incdec_property_zval(zval *prop, zend_property_info *prop_info, int inc OPLINE_DC EXECUTE_DATA_DC)
 {
        if (EXPECTED(Z_TYPE_P(prop) == IS_LONG)) {
index d94fe6843542dcd10ec7cb8a9893012e194812f1..884a8552e4ec61c086d04d0e8f44401755d15739 100644 (file)
@@ -1401,34 +1401,17 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY, SPEC(RETVAL))
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval old;
-                       ZVAL_COPY(&old, var_ptr);
-
-                       increment_function(var_ptr);
-
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE(old) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 1);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-                               FREE_OP1_VAR_PTR();
-                               HANDLE_EXCEPTION();
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-                               FREE_OP1_VAR_PTR();
-                               HANDLE_EXCEPTION();
-                       } else {
-                               zval_ptr_dtor(&old);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, NULL, 1 EXECUTE_DATA_CC);
+                               break;
                        }
-               } else {
-                       increment_function(var_ptr);
                }
-       } else {
                increment_function(var_ptr);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -1467,35 +1450,18 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY, SPEC(RETVAL))
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval old;
-                       ZVAL_COPY(&old, var_ptr);
-
-                       decrement_function(var_ptr);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
 
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE(old) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 0);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-                               FREE_OP1_VAR_PTR();
-                               HANDLE_EXCEPTION();
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-                               FREE_OP1_VAR_PTR();
-                               HANDLE_EXCEPTION();
-                       } else {
-                               zval_ptr_dtor(&old);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, NULL, 0 EXECUTE_DATA_CC);
+                               break;
                        }
-               } else {
-                       decrement_function(var_ptr);
                }
-       } else {
                decrement_function(var_ptr);
-       }
+       } while (0);
 
        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -1530,28 +1496,20 @@ ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY)
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-
-               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
-
-               increment_function(var_ptr);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
 
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE_P(EX_VAR(opline->result.var)) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 1);
-                               ZVAL_COPY_VALUE(var_ptr, EX_VAR(opline->result.var));
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, EX_VAR(opline->result.var));
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, EX_VAR(opline->result.var), 1 EXECUTE_DATA_CC);
+                               break;
                        }
                }
-       } else {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
 
                increment_function(var_ptr);
-       }
+       } while (0);
 
        FREE_OP1_VAR_PTR();
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -1582,28 +1540,20 @@ ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY)
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-
-               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
-
-               decrement_function(var_ptr);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
 
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE_P(EX_VAR(opline->result.var)) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 0);
-                               ZVAL_COPY_VALUE(var_ptr, EX_VAR(opline->result.var));
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, EX_VAR(opline->result.var));
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, EX_VAR(opline->result.var), 0 EXECUTE_DATA_CC);
+                               break;
                        }
                }
-       } else {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
 
                decrement_function(var_ptr);
-       }
+       } while (0);
 
        FREE_OP1_VAR_PTR();
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
index c298f5a0689397bb6a368bef36983e4f0e4866af..22b96eb82288a7b4863134ae83fef44043940f8f 100644 (file)
@@ -22580,34 +22580,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval old;
-                       ZVAL_COPY(&old, var_ptr);
-
-                       increment_function(var_ptr);
-
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE(old) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 1);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-                               if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
-                               HANDLE_EXCEPTION();
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-                               if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
-                               HANDLE_EXCEPTION();
-                       } else {
-                               zval_ptr_dtor(&old);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, NULL, 1 EXECUTE_DATA_CC);
+                               break;
                        }
-               } else {
-                       increment_function(var_ptr);
                }
-       } else {
                increment_function(var_ptr);
-       }
+       } while (0);
 
        if (UNEXPECTED(0)) {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -22646,34 +22629,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_H
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval old;
-                       ZVAL_COPY(&old, var_ptr);
-
-                       increment_function(var_ptr);
-
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE(old) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 1);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-                               if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
-                               HANDLE_EXCEPTION();
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-                               if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
-                               HANDLE_EXCEPTION();
-                       } else {
-                               zval_ptr_dtor(&old);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, NULL, 1 EXECUTE_DATA_CC);
+                               break;
                        }
-               } else {
-                       increment_function(var_ptr);
                }
-       } else {
                increment_function(var_ptr);
-       }
+       } while (0);
 
        if (UNEXPECTED(1)) {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -22712,35 +22678,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval old;
-                       ZVAL_COPY(&old, var_ptr);
-
-                       decrement_function(var_ptr);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
 
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE(old) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 0);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-                               if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
-                               HANDLE_EXCEPTION();
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-                               if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
-                               HANDLE_EXCEPTION();
-                       } else {
-                               zval_ptr_dtor(&old);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, NULL, 0 EXECUTE_DATA_CC);
+                               break;
                        }
-               } else {
-                       decrement_function(var_ptr);
                }
-       } else {
                decrement_function(var_ptr);
-       }
+       } while (0);
 
        if (UNEXPECTED(0)) {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -22779,35 +22728,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_H
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval old;
-                       ZVAL_COPY(&old, var_ptr);
-
-                       decrement_function(var_ptr);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
 
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE(old) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 0);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-                               if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
-                               HANDLE_EXCEPTION();
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-                               if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
-                               HANDLE_EXCEPTION();
-                       } else {
-                               zval_ptr_dtor(&old);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, NULL, 0 EXECUTE_DATA_CC);
+                               break;
                        }
-               } else {
-                       decrement_function(var_ptr);
                }
-       } else {
                decrement_function(var_ptr);
-       }
+       } while (0);
 
        if (UNEXPECTED(1)) {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -22842,28 +22774,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-
-               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
-
-               increment_function(var_ptr);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
 
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE_P(EX_VAR(opline->result.var)) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 1);
-                               ZVAL_COPY_VALUE(var_ptr, EX_VAR(opline->result.var));
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, EX_VAR(opline->result.var));
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, EX_VAR(opline->result.var), 1 EXECUTE_DATA_CC);
+                               break;
                        }
                }
-       } else {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
 
                increment_function(var_ptr);
-       }
+       } while (0);
 
        if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -22894,28 +22818,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-
-               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
-
-               decrement_function(var_ptr);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
 
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE_P(EX_VAR(opline->result.var)) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 0);
-                               ZVAL_COPY_VALUE(var_ptr, EX_VAR(opline->result.var));
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, EX_VAR(opline->result.var));
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, EX_VAR(opline->result.var), 0 EXECUTE_DATA_CC);
+                               break;
                        }
                }
-       } else {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
 
                decrement_function(var_ptr);
-       }
+       } while (0);
 
        if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -41699,34 +41615,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RETVAL_UNUSED_
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval old;
-                       ZVAL_COPY(&old, var_ptr);
-
-                       increment_function(var_ptr);
-
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE(old) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 1);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-
-                               HANDLE_EXCEPTION();
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-
-                               HANDLE_EXCEPTION();
-                       } else {
-                               zval_ptr_dtor(&old);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, NULL, 1 EXECUTE_DATA_CC);
+                               break;
                        }
-               } else {
-                       increment_function(var_ptr);
                }
-       } else {
                increment_function(var_ptr);
-       }
+       } while (0);
 
        if (UNEXPECTED(0)) {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -41764,34 +41663,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RETVAL_USED_HA
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval old;
-                       ZVAL_COPY(&old, var_ptr);
-
-                       increment_function(var_ptr);
-
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE(old) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 1);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-
-                               HANDLE_EXCEPTION();
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-
-                               HANDLE_EXCEPTION();
-                       } else {
-                               zval_ptr_dtor(&old);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, NULL, 1 EXECUTE_DATA_CC);
+                               break;
                        }
-               } else {
-                       increment_function(var_ptr);
                }
-       } else {
                increment_function(var_ptr);
-       }
+       } while (0);
 
        if (UNEXPECTED(1)) {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -41829,35 +41711,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RETVAL_UNUSED_
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval old;
-                       ZVAL_COPY(&old, var_ptr);
-
-                       decrement_function(var_ptr);
-
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE(old) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 0);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-
-                               HANDLE_EXCEPTION();
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
 
-                               HANDLE_EXCEPTION();
-                       } else {
-                               zval_ptr_dtor(&old);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, NULL, 0 EXECUTE_DATA_CC);
+                               break;
                        }
-               } else {
-                       decrement_function(var_ptr);
                }
-       } else {
                decrement_function(var_ptr);
-       }
+       } while (0);
 
        if (UNEXPECTED(0)) {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -41895,35 +41760,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RETVAL_USED_HA
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       zval old;
-                       ZVAL_COPY(&old, var_ptr);
-
-                       decrement_function(var_ptr);
-
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE(old) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 0);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
-
-                               HANDLE_EXCEPTION();
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, &old);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
 
-                               HANDLE_EXCEPTION();
-                       } else {
-                               zval_ptr_dtor(&old);
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, NULL, 0 EXECUTE_DATA_CC);
+                               break;
                        }
-               } else {
-                       decrement_function(var_ptr);
                }
-       } else {
                decrement_function(var_ptr);
-       }
+       } while (0);
 
        if (UNEXPECTED(1)) {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
@@ -41957,28 +41805,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-
-               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
-
-               increment_function(var_ptr);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
 
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE_P(EX_VAR(opline->result.var)) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 1);
-                               ZVAL_COPY_VALUE(var_ptr, EX_VAR(opline->result.var));
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, EX_VAR(opline->result.var));
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, EX_VAR(opline->result.var), 1 EXECUTE_DATA_CC);
+                               break;
                        }
                }
-       } else {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
 
                increment_function(var_ptr);
-       }
+       } while (0);
 
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }
@@ -42008,28 +41848,20 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_
                ZVAL_UNDEFINED_OP1();
        }
 
-       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
-               zend_reference *ref = Z_REF_P(var_ptr);
-               var_ptr = Z_REFVAL_P(var_ptr);
-
-               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
-
-               decrement_function(var_ptr);
+       do {
+               if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
+                       zend_reference *ref = Z_REF_P(var_ptr);
+                       var_ptr = Z_REFVAL_P(var_ptr);
 
-               if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
-                       if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_DOUBLE) && Z_TYPE_P(EX_VAR(opline->result.var)) == IS_LONG) {
-                               zend_throw_incdec_ref_error(ref, 0);
-                               ZVAL_COPY_VALUE(var_ptr, EX_VAR(opline->result.var));
-                       } else if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, var_ptr, EX_USES_STRICT_TYPES()))) {
-                               zval_ptr_dtor(var_ptr);
-                               ZVAL_COPY_VALUE(var_ptr, EX_VAR(opline->result.var));
+                       if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
+                               zend_incdec_typed_ref(ref, EX_VAR(opline->result.var), 0 EXECUTE_DATA_CC);
+                               break;
                        }
                }
-       } else {
                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
 
                decrement_function(var_ptr);
-       }
+       } while (0);
 
        ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }