diff --git a/Zend/tests/dynamic_call_freeing.phpt b/Zend/tests/dynamic_call_freeing.phpt new file mode 100644 index 00000000000..d1240092952 --- /dev/null +++ b/Zend/tests/dynamic_call_freeing.phpt @@ -0,0 +1,28 @@ +--TEST-- +Freeing of function "name" when dynamic call fails +--FILE-- +getMessage(), "\n"; +} +try { + $bar = ["bar"]; + (["foo"] + $bar)(); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +try { + (new stdClass)(); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Call to undefined function foobar() +Function name must be a string +Function name must be a string diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 68b91ba7d73..ac70ec003f4 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3689,11 +3689,11 @@ ZEND_VM_C_LABEL(try_function_name): call = NULL; } + FREE_OP2(); if (UNEXPECTED(!call)) { HANDLE_EXCEPTION(); } - FREE_OP2(); if (OP2_TYPE & (IS_VAR|IS_TMP_VAR)) { if (UNEXPECTED(EG(exception))) { if (call) { @@ -3705,8 +3705,6 @@ ZEND_VM_C_LABEL(try_function_name): } HANDLE_EXCEPTION(); } - } else if (UNEXPECTED(!call)) { - HANDLE_EXCEPTION(); } call->prev_execute_data = EX(call); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index cc6861d527f..859f8bf9d7e 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2865,8 +2865,6 @@ try_function_name: } HANDLE_EXCEPTION(); } - } else if (UNEXPECTED(!call)) { - HANDLE_EXCEPTION(); } call->prev_execute_data = EX(call); @@ -3018,11 +3016,11 @@ try_function_name: call = NULL; } + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if (UNEXPECTED(!call)) { HANDLE_EXCEPTION(); } - zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) { if (UNEXPECTED(EG(exception))) { if (call) { @@ -3034,8 +3032,6 @@ try_function_name: } HANDLE_EXCEPTION(); } - } else if (UNEXPECTED(!call)) { - HANDLE_EXCEPTION(); } call->prev_execute_data = EX(call); @@ -3150,8 +3146,6 @@ try_function_name: } HANDLE_EXCEPTION(); } - } else if (UNEXPECTED(!call)) { - HANDLE_EXCEPTION(); } call->prev_execute_data = EX(call);