Fixed bug #73338 (Exception thrown from error handler may crash)
authorBob Weinand <bobwei9@hotmail.com>
Tue, 18 Oct 2016 12:13:20 +0000 (14:13 +0200)
committerBob Weinand <bobwei9@hotmail.com>
Tue, 18 Oct 2016 12:14:24 +0000 (14:14 +0200)
NEWS
Zend/tests/bug73338.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index be20d3ba963fe62543b5fa87ba553094d088946b..4be67717ff0434e3b93f39dcf9ec7d7151c3b12e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,8 @@ PHP                                                                        NEWS
   . Fixed bug #73215 (uniqid() should use better random source). (Yasuo)
   . Fixed bug #73337 (try/catch not working with two exceptions inside a same
     operation). (Dmitry)
+  . Fixed bug #73338 (Exception thrown from error handler causes valgrind
+    warnings (and crashes)). (Bob, Dmitry)
 
 - GD:
   . Fixed bug #73213 (Integer overflow in imageline() with antialiasing). (cmb)
diff --git a/Zend/tests/bug73338.phpt b/Zend/tests/bug73338.phpt
new file mode 100644 (file)
index 0000000..df4c3b6
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+Bug #73338: Ensure exceptions in function init opcodes are cleaned properly
+--FILE--
+<?php
+
+try { call_user_func(new class { function __destruct () { throw new Error; } }); } catch (Error $e) {}
+
+set_error_handler(function() { throw new Error; });
+
+try { var_dump(new stdClass, call_user_func("fail")); } catch (Error $e) {}
+
+try { (function() { call_user_func("fail"); })(); } catch (Error $e) {}
+
+try { [new class { static function foo() {} function __destruct () { throw new Error; } }, "foo"](); } catch (Error $e) {}
+
+?>
+--EXPECTF--
+Warning: call_user_func() expects parameter 1 to be a valid callback, no array or string given in %s on line %d
index dcd460ad5d3750b4cf1729defbd88401524e2fdd..6693ef316ff11d4526c6dc44d5c0a04ad340b74a 100644 (file)
@@ -3012,15 +3012,19 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR
                GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
+       FREE_OP2();
+       FREE_OP1();
+
+       if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               HANDLE_EXCEPTION();
+       }
+
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       FREE_OP2();
-       FREE_OP1();
-
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSED|CV)
@@ -3161,7 +3165,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST)
@@ -3283,7 +3287,6 @@ ZEND_VM_C_LABEL(try_function_name):
                        called_scope = NULL;
                        object = NULL;
                }
-               FREE_OP2();
        } else if (OP2_TYPE != IS_CONST &&
            EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
                Z_OBJ_HANDLER_P(function_name, get_closure) &&
@@ -3297,7 +3300,6 @@ ZEND_VM_C_LABEL(try_function_name):
                        call_info |= ZEND_CALL_RELEASE_THIS;
                        GC_REFCOUNT(object)++; /* For $this pointer */
                }
-               FREE_OP2();
        } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
                        zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
                zval *obj;
@@ -3381,7 +3383,6 @@ ZEND_VM_C_LABEL(try_function_name):
                                GC_REFCOUNT(object)++; /* For $this pointer */
                        }
                }
-               FREE_OP2();
        } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(function_name) == IS_REFERENCE) {
                function_name = Z_REFVAL_P(function_name);
                ZEND_VM_C_GOTO(try_function_name);
@@ -3396,6 +3397,18 @@ ZEND_VM_C_LABEL(try_function_name):
                FREE_OP2();
                HANDLE_EXCEPTION();
        }
+
+       FREE_OP2();
+       if ((OP2_TYPE & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               if (call_info & ZEND_CALL_RELEASE_THIS) {
+                       zend_object_release(object);
+               }
+               if (fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
+                       zend_string_release(fbc->common.function_name);
+                       zend_free_trampoline(fbc);
+               }
+               HANDLE_EXCEPTION();
+       }
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, object);
        call->prev_execute_data = EX(call);
@@ -3421,6 +3434,19 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV)
        function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
        if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
                func = fcc.function_handler;
+               called_scope = fcc.called_scope;
+               object = fcc.object;
+               if (error) {
+                       efree(error);
+                       /* This is the only soft error is_callable() can generate */
+                       zend_error(E_DEPRECATED,
+                               "Non-static method %s::%s() should not be called statically",
+                               ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name));
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+                               FREE_OP2();
+                               HANDLE_EXCEPTION();
+                       }
+               }
                if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
                        /* Delay closure destruction until its invocation */
                        if (OP2_TYPE & (IS_VAR|IS_CV)) {
@@ -3430,25 +3456,28 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV)
                        GC_REFCOUNT((zend_object*)func->common.prototype)++;
                        call_info |= ZEND_CALL_CLOSURE;
                }
-               called_scope = fcc.called_scope;
-               object = fcc.object;
                if (object) {
                        call_info |= ZEND_CALL_RELEASE_THIS;
                        GC_REFCOUNT(object)++; /* For $this pointer */
                }
-               if (error) {
-                       efree(error);
-                       /* This is the only soft error is_callable() can generate */
-                       zend_error(E_DEPRECATED,
-                               "Non-static method %s::%s() should not be called statically",
-                               ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name));
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               HANDLE_EXCEPTION();
+
+               FREE_OP2();
+               if ((OP2_TYPE & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
+                       if (call_info & ZEND_CALL_CLOSURE) {
+                               zend_object_release((zend_object*)func->common.prototype);
+                       }
+                       if (call_info & ZEND_CALL_RELEASE_THIS) {
+                               zend_object_release(object);
                        }
+                       HANDLE_EXCEPTION();
                }
        } else {
                zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
                efree(error);
+               FREE_OP2();
+               if (UNEXPECTED(EG(exception))) {
+                       HANDLE_EXCEPTION();
+               }
                func = (zend_function*)&zend_pass_function;
                called_scope = NULL;
                object = NULL;
@@ -3459,8 +3488,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV)
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       FREE_OP2();
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
@@ -4946,7 +4974,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
                        ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
                }
 
-               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+               ZEND_VM_NEXT_OPCODE();
        }
 }
 
index 4bc72bd24f67e7606f7dafcde4159f2ec8c2bb7f..2c90e0073ee28ee381cb2b93204ca7eb36e92ec7 100644 (file)
@@ -1995,7 +1995,6 @@ try_function_name:
                        called_scope = NULL;
                        object = NULL;
                }
-
        } else if (IS_CONST != IS_CONST &&
            EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
                Z_OBJ_HANDLER_P(function_name, get_closure) &&
@@ -2009,7 +2008,6 @@ try_function_name:
                        call_info |= ZEND_CALL_RELEASE_THIS;
                        GC_REFCOUNT(object)++; /* For $this pointer */
                }
-
        } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
                        zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
                zval *obj;
@@ -2093,7 +2091,6 @@ try_function_name:
                                GC_REFCOUNT(object)++; /* For $this pointer */
                        }
                }
-
        } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(function_name) == IS_REFERENCE) {
                function_name = Z_REFVAL_P(function_name);
                goto try_function_name;
@@ -2108,6 +2105,17 @@ try_function_name:
 
                HANDLE_EXCEPTION();
        }
+
+       if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               if (call_info & ZEND_CALL_RELEASE_THIS) {
+                       zend_object_release(object);
+               }
+               if (fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
+                       zend_string_release(fbc->common.function_name);
+                       zend_free_trampoline(fbc);
+               }
+               HANDLE_EXCEPTION();
+       }
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, object);
        call->prev_execute_data = EX(call);
@@ -2418,7 +2426,6 @@ try_function_name:
                        called_scope = NULL;
                        object = NULL;
                }
-
        } else if (IS_CV != IS_CONST &&
            EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
                Z_OBJ_HANDLER_P(function_name, get_closure) &&
@@ -2432,7 +2439,6 @@ try_function_name:
                        call_info |= ZEND_CALL_RELEASE_THIS;
                        GC_REFCOUNT(object)++; /* For $this pointer */
                }
-
        } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
                        zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
                zval *obj;
@@ -2516,7 +2522,6 @@ try_function_name:
                                GC_REFCOUNT(object)++; /* For $this pointer */
                        }
                }
-
        } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(function_name) == IS_REFERENCE) {
                function_name = Z_REFVAL_P(function_name);
                goto try_function_name;
@@ -2531,6 +2536,17 @@ try_function_name:
 
                HANDLE_EXCEPTION();
        }
+
+       if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               if (call_info & ZEND_CALL_RELEASE_THIS) {
+                       zend_object_release(object);
+               }
+               if (fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
+                       zend_string_release(fbc->common.function_name);
+                       zend_free_trampoline(fbc);
+               }
+               HANDLE_EXCEPTION();
+       }
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, object);
        call->prev_execute_data = EX(call);
@@ -2674,7 +2690,6 @@ try_function_name:
                        called_scope = NULL;
                        object = NULL;
                }
-               zval_ptr_dtor_nogc(free_op2);
        } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST &&
            EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
                Z_OBJ_HANDLER_P(function_name, get_closure) &&
@@ -2688,7 +2703,6 @@ try_function_name:
                        call_info |= ZEND_CALL_RELEASE_THIS;
                        GC_REFCOUNT(object)++; /* For $this pointer */
                }
-               zval_ptr_dtor_nogc(free_op2);
        } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
                        zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
                zval *obj;
@@ -2772,7 +2786,6 @@ try_function_name:
                                GC_REFCOUNT(object)++; /* For $this pointer */
                        }
                }
-               zval_ptr_dtor_nogc(free_op2);
        } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(function_name) == IS_REFERENCE) {
                function_name = Z_REFVAL_P(function_name);
                goto try_function_name;
@@ -2787,6 +2800,18 @@ try_function_name:
                zval_ptr_dtor_nogc(free_op2);
                HANDLE_EXCEPTION();
        }
+
+       zval_ptr_dtor_nogc(free_op2);
+       if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               if (call_info & ZEND_CALL_RELEASE_THIS) {
+                       zend_object_release(object);
+               }
+               if (fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
+                       zend_string_release(fbc->common.function_name);
+                       zend_free_trampoline(fbc);
+               }
+               HANDLE_EXCEPTION();
+       }
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, object);
        call->prev_execute_data = EX(call);
@@ -3367,7 +3392,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OP
                        ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
                }
 
-               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+               ZEND_VM_NEXT_OPCODE();
        }
 }
 
@@ -5594,13 +5619,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CO
                GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
+
+       if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               HANDLE_EXCEPTION();
+       }
+
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -5741,7 +5770,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -5761,6 +5790,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS
        function_name = EX_CONSTANT(opline->op2);
        if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
                func = fcc.function_handler;
+               called_scope = fcc.called_scope;
+               object = fcc.object;
+               if (error) {
+                       efree(error);
+                       /* This is the only soft error is_callable() can generate */
+                       zend_error(E_DEPRECATED,
+                               "Non-static method %s::%s() should not be called statically",
+                               ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name));
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+
+                               HANDLE_EXCEPTION();
+                       }
+               }
                if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
                        /* Delay closure destruction until its invocation */
                        if (IS_CONST & (IS_VAR|IS_CV)) {
@@ -5770,25 +5812,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS
                        GC_REFCOUNT((zend_object*)func->common.prototype)++;
                        call_info |= ZEND_CALL_CLOSURE;
                }
-               called_scope = fcc.called_scope;
-               object = fcc.object;
                if (object) {
                        call_info |= ZEND_CALL_RELEASE_THIS;
                        GC_REFCOUNT(object)++; /* For $this pointer */
                }
-               if (error) {
-                       efree(error);
-                       /* This is the only soft error is_callable() can generate */
-                       zend_error(E_DEPRECATED,
-                               "Non-static method %s::%s() should not be called statically",
-                               ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name));
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               HANDLE_EXCEPTION();
+
+               if ((IS_CONST & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
+                       if (call_info & ZEND_CALL_CLOSURE) {
+                               zend_object_release((zend_object*)func->common.prototype);
                        }
+                       if (call_info & ZEND_CALL_RELEASE_THIS) {
+                               zend_object_release(object);
+                       }
+                       HANDLE_EXCEPTION();
                }
        } else {
                zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
                efree(error);
+
+               if (UNEXPECTED(EG(exception))) {
+                       HANDLE_EXCEPTION();
+               }
                func = (zend_function*)&zend_pass_function;
                called_scope = NULL;
                object = NULL;
@@ -5799,7 +5843,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONS
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -7740,7 +7784,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -9346,13 +9390,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV
                GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
+
+       if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               HANDLE_EXCEPTION();
+       }
+
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -9493,7 +9541,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -9513,6 +9561,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
        function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
        if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
                func = fcc.function_handler;
+               called_scope = fcc.called_scope;
+               object = fcc.object;
+               if (error) {
+                       efree(error);
+                       /* This is the only soft error is_callable() can generate */
+                       zend_error(E_DEPRECATED,
+                               "Non-static method %s::%s() should not be called statically",
+                               ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name));
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+
+                               HANDLE_EXCEPTION();
+                       }
+               }
                if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
                        /* Delay closure destruction until its invocation */
                        if (IS_CV & (IS_VAR|IS_CV)) {
@@ -9522,25 +9583,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
                        GC_REFCOUNT((zend_object*)func->common.prototype)++;
                        call_info |= ZEND_CALL_CLOSURE;
                }
-               called_scope = fcc.called_scope;
-               object = fcc.object;
                if (object) {
                        call_info |= ZEND_CALL_RELEASE_THIS;
                        GC_REFCOUNT(object)++; /* For $this pointer */
                }
-               if (error) {
-                       efree(error);
-                       /* This is the only soft error is_callable() can generate */
-                       zend_error(E_DEPRECATED,
-                               "Non-static method %s::%s() should not be called statically",
-                               ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name));
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               HANDLE_EXCEPTION();
+
+               if ((IS_CV & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
+                       if (call_info & ZEND_CALL_CLOSURE) {
+                               zend_object_release((zend_object*)func->common.prototype);
+                       }
+                       if (call_info & ZEND_CALL_RELEASE_THIS) {
+                               zend_object_release(object);
                        }
+                       HANDLE_EXCEPTION();
                }
        } else {
                zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
                efree(error);
+
+               if (UNEXPECTED(EG(exception))) {
+                       HANDLE_EXCEPTION();
+               }
                func = (zend_function*)&zend_pass_function;
                called_scope = NULL;
                object = NULL;
@@ -9551,7 +9614,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -11176,14 +11239,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_TM
                GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
+       zval_ptr_dtor_nogc(free_op2);
+
+       if ((IS_CONST & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               HANDLE_EXCEPTION();
+       }
+
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       zval_ptr_dtor_nogc(free_op2);
-
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -11324,7 +11391,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -11344,6 +11411,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
        function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
        if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
                func = fcc.function_handler;
+               called_scope = fcc.called_scope;
+               object = fcc.object;
+               if (error) {
+                       efree(error);
+                       /* This is the only soft error is_callable() can generate */
+                       zend_error(E_DEPRECATED,
+                               "Non-static method %s::%s() should not be called statically",
+                               ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name));
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+                               zval_ptr_dtor_nogc(free_op2);
+                               HANDLE_EXCEPTION();
+                       }
+               }
                if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
                        /* Delay closure destruction until its invocation */
                        if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) {
@@ -11353,25 +11433,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
                        GC_REFCOUNT((zend_object*)func->common.prototype)++;
                        call_info |= ZEND_CALL_CLOSURE;
                }
-               called_scope = fcc.called_scope;
-               object = fcc.object;
                if (object) {
                        call_info |= ZEND_CALL_RELEASE_THIS;
                        GC_REFCOUNT(object)++; /* For $this pointer */
                }
-               if (error) {
-                       efree(error);
-                       /* This is the only soft error is_callable() can generate */
-                       zend_error(E_DEPRECATED,
-                               "Non-static method %s::%s() should not be called statically",
-                               ZSTR_VAL(func->common.scope->name), ZSTR_VAL(func->common.function_name));
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               HANDLE_EXCEPTION();
+
+               zval_ptr_dtor_nogc(free_op2);
+               if (((IS_TMP_VAR|IS_VAR) & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
+                       if (call_info & ZEND_CALL_CLOSURE) {
+                               zend_object_release((zend_object*)func->common.prototype);
                        }
+                       if (call_info & ZEND_CALL_RELEASE_THIS) {
+                               zend_object_release(object);
+                       }
+                       HANDLE_EXCEPTION();
                }
        } else {
                zend_internal_type_error(EX_USES_STRICT_TYPES(), "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
                efree(error);
+               zval_ptr_dtor_nogc(free_op2);
+               if (UNEXPECTED(EG(exception))) {
+                       HANDLE_EXCEPTION();
+               }
                func = (zend_function*)&zend_pass_function;
                called_scope = NULL;
                object = NULL;
@@ -11382,8 +11465,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPV
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       zval_ptr_dtor_nogc(free_op2);
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -15482,7 +15564,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCO
                        ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
                }
 
-               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+               ZEND_VM_NEXT_OPCODE();
        }
 }
 
@@ -17726,7 +17808,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -19365,7 +19447,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -21010,7 +21092,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -22602,7 +22684,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -23985,13 +24067,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
                GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
+
+       if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               HANDLE_EXCEPTION();
+       }
+
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -26412,13 +26498,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
                GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
+
+       if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               HANDLE_EXCEPTION();
+       }
+
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -27916,14 +28006,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
                GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
+       zval_ptr_dtor_nogc(free_op2);
+
+       if ((IS_UNUSED & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               HANDLE_EXCEPTION();
+       }
+
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       zval_ptr_dtor_nogc(free_op2);
-
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -32200,13 +32294,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST
                GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
+
+       if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               HANDLE_EXCEPTION();
+       }
+
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -37304,13 +37402,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
                GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
+
+       if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               HANDLE_EXCEPTION();
+       }
+
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -39899,14 +40001,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
                GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
+       zval_ptr_dtor_nogc(free_op2);
+
+       if ((IS_CV & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               HANDLE_EXCEPTION();
+       }
+
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       zval_ptr_dtor_nogc(free_op2);
-
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -42141,14 +42247,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
                GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
+       zval_ptr_dtor_nogc(free_op1);
+
+       if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               HANDLE_EXCEPTION();
+       }
+
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       zval_ptr_dtor_nogc(free_op1);
-
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -44289,14 +44399,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
                GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
+       zval_ptr_dtor_nogc(free_op1);
+
+       if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               HANDLE_EXCEPTION();
+       }
+
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       zval_ptr_dtor_nogc(free_op1);
-
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -45435,15 +45549,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
                GC_REFCOUNT(obj)++; /* For $this pointer */
        }
 
+       zval_ptr_dtor_nogc(free_op2);
+       zval_ptr_dtor_nogc(free_op1);
+
+       if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
+               HANDLE_EXCEPTION();
+       }
+
        call = zend_vm_stack_push_call_frame(call_info,
                fbc, opline->extended_value, called_scope, obj);
        call->prev_execute_data = EX(call);
        EX(call) = call;
 
-       zval_ptr_dtor_nogc(free_op2);
-       zval_ptr_dtor_nogc(free_op1);
-
-       ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
 }
 
 static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)