mirror of
https://github.com/php/php-src.git
synced 2024-11-27 11:53:33 +08:00
Improve exception handling for abstract/deprecated calls
Reuse existing arg freeing loop instead of duplicating it. Additionally also handle deprecated in DO_FCALL_BY_NAME.
This commit is contained in:
parent
4bb7282742
commit
b6f76aca54
@ -13,6 +13,14 @@ try {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
$ret = new stdClass;
|
||||
try {
|
||||
$ret = Test::method(new stdClass);
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Cannot call abstract method Test::method()
|
||||
Cannot call abstract method Test::method()
|
||||
|
43
Zend/tests/call_to_deprecated_function_args.phpt
Normal file
43
Zend/tests/call_to_deprecated_function_args.phpt
Normal file
@ -0,0 +1,43 @@
|
||||
--TEST--
|
||||
Check that arguments are freed when calling a deprecated function
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
set_error_handler(function($code, $msg) {
|
||||
throw new Error($msg);
|
||||
});
|
||||
|
||||
try {
|
||||
ezmlm_hash(new stdClass);
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
$ret = new stdClass;
|
||||
try {
|
||||
$ret = ezmlm_hash(new stdClass);
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
$fn = 'ezmlm_hash';
|
||||
$fn(new stdClass);
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
$ret = new stdClass;
|
||||
try {
|
||||
$fn = 'ezmlm_hash';
|
||||
$ret = $fn(new stdClass);
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Function ezmlm_hash() is deprecated
|
||||
Function ezmlm_hash() is deprecated
|
||||
Function ezmlm_hash() is deprecated
|
||||
Function ezmlm_hash() is deprecated
|
@ -1132,7 +1132,6 @@ static zend_never_inline int zend_verify_internal_arg_types(zend_function *fbc,
|
||||
dummy_cache_slot = NULL;
|
||||
if (UNEXPECTED(!zend_verify_arg_type(fbc, i + 1, p, NULL, &dummy_cache_slot))) {
|
||||
EG(current_execute_data) = call->prev_execute_data;
|
||||
zend_vm_stack_free_args(call);
|
||||
return 0;
|
||||
}
|
||||
p++;
|
||||
|
@ -4075,8 +4075,12 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
|
||||
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
|
||||
zend_deprecated_function(fbc);
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
UNDEF_RESULT();
|
||||
HANDLE_EXCEPTION();
|
||||
UNDEF_RESULT();
|
||||
if (!RETURN_VALUE_USED(opline)) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
ZEND_VM_C_GOTO(fcall_end);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4085,10 +4089,12 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
|
||||
|
||||
if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)
|
||||
&& UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) {
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
zend_rethrow_exception(execute_data);
|
||||
UNDEF_RESULT();
|
||||
HANDLE_EXCEPTION();
|
||||
UNDEF_RESULT();
|
||||
if (!RETURN_VALUE_USED(opline)) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
ZEND_VM_C_GOTO(fcall_end);
|
||||
}
|
||||
|
||||
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
|
||||
@ -4106,6 +4112,8 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
|
||||
#endif
|
||||
|
||||
EG(current_execute_data) = execute_data;
|
||||
|
||||
ZEND_VM_C_LABEL(fcall_end):
|
||||
zend_vm_stack_free_args(call);
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
|
||||
@ -4128,6 +4136,7 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
|
||||
zend_execute_data *call = EX(call);
|
||||
zend_function *fbc = call->func;
|
||||
zval *ret;
|
||||
zval retval;
|
||||
|
||||
SAVE_OPLINE();
|
||||
EX(call) = call->prev_execute_data;
|
||||
@ -4136,7 +4145,10 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
|
||||
zend_abstract_method(fbc);
|
||||
ZEND_VM_C_LABEL(fcall_except):
|
||||
UNDEF_RESULT();
|
||||
zend_vm_stack_free_args(call);
|
||||
if (!RETURN_VALUE_USED(opline)) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
ZEND_VM_C_GOTO(fcall_end);
|
||||
} else {
|
||||
zend_deprecated_function(fbc);
|
||||
@ -4167,15 +4179,12 @@ ZEND_VM_C_LABEL(fcall_except):
|
||||
zend_execute_ex(call);
|
||||
}
|
||||
} else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) {
|
||||
zval retval;
|
||||
|
||||
call->prev_execute_data = execute_data;
|
||||
EG(current_execute_data) = call;
|
||||
|
||||
if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)
|
||||
&& UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) {
|
||||
UNDEF_RESULT();
|
||||
ZEND_VM_C_GOTO(fcall_end);
|
||||
ZEND_VM_C_GOTO(fcall_except);
|
||||
}
|
||||
|
||||
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
|
||||
@ -4198,15 +4207,13 @@ ZEND_VM_C_LABEL(fcall_except):
|
||||
#endif
|
||||
|
||||
EG(current_execute_data) = execute_data;
|
||||
zend_vm_stack_free_args(call);
|
||||
|
||||
ZEND_VM_C_LABEL(fcall_end):
|
||||
zend_vm_stack_free_args(call);
|
||||
if (!RETURN_VALUE_USED(opline)) {
|
||||
i_zval_ptr_dtor(ret);
|
||||
}
|
||||
|
||||
} else { /* ZEND_OVERLOADED_FUNCTION */
|
||||
zval retval;
|
||||
|
||||
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
|
||||
|
||||
call->prev_execute_data = execute_data;
|
||||
@ -4221,7 +4228,6 @@ ZEND_VM_C_LABEL(fcall_except):
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_C_LABEL(fcall_end):
|
||||
if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) {
|
||||
OBJ_RELEASE(Z_OBJ(call->This));
|
||||
}
|
||||
@ -8291,14 +8297,13 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
|
||||
|
||||
EG(current_execute_data) = call->prev_execute_data;
|
||||
|
||||
ZEND_VM_C_LABEL(call_trampoline_end):
|
||||
zend_vm_stack_free_args(call);
|
||||
|
||||
if (ret == &retval) {
|
||||
zval_ptr_dtor(ret);
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_C_LABEL(call_trampoline_end):
|
||||
execute_data = EG(current_execute_data);
|
||||
|
||||
if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) {
|
||||
|
@ -1413,8 +1413,12 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S
|
||||
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
|
||||
zend_deprecated_function(fbc);
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
UNDEF_RESULT();
|
||||
HANDLE_EXCEPTION();
|
||||
UNDEF_RESULT();
|
||||
if (!0) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
goto fcall_end;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1423,10 +1427,12 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S
|
||||
|
||||
if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)
|
||||
&& UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) {
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
zend_rethrow_exception(execute_data);
|
||||
UNDEF_RESULT();
|
||||
HANDLE_EXCEPTION();
|
||||
UNDEF_RESULT();
|
||||
if (!0) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
goto fcall_end;
|
||||
}
|
||||
|
||||
ret = 0 ? EX_VAR(opline->result.var) : &retval;
|
||||
@ -1444,6 +1450,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S
|
||||
#endif
|
||||
|
||||
EG(current_execute_data) = execute_data;
|
||||
|
||||
fcall_end:
|
||||
zend_vm_stack_free_args(call);
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
|
||||
@ -1489,8 +1497,12 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S
|
||||
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
|
||||
zend_deprecated_function(fbc);
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
UNDEF_RESULT();
|
||||
HANDLE_EXCEPTION();
|
||||
UNDEF_RESULT();
|
||||
if (!1) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
goto fcall_end;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1499,10 +1511,12 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S
|
||||
|
||||
if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)
|
||||
&& UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) {
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
zend_rethrow_exception(execute_data);
|
||||
UNDEF_RESULT();
|
||||
HANDLE_EXCEPTION();
|
||||
UNDEF_RESULT();
|
||||
if (!1) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
goto fcall_end;
|
||||
}
|
||||
|
||||
ret = 1 ? EX_VAR(opline->result.var) : &retval;
|
||||
@ -1520,6 +1534,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S
|
||||
#endif
|
||||
|
||||
EG(current_execute_data) = execute_data;
|
||||
|
||||
fcall_end:
|
||||
zend_vm_stack_free_args(call);
|
||||
zend_vm_stack_free_call_frame(call);
|
||||
|
||||
@ -1542,6 +1558,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
|
||||
zend_execute_data *call = EX(call);
|
||||
zend_function *fbc = call->func;
|
||||
zval *ret;
|
||||
zval retval;
|
||||
|
||||
SAVE_OPLINE();
|
||||
EX(call) = call->prev_execute_data;
|
||||
@ -1550,7 +1567,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
|
||||
zend_abstract_method(fbc);
|
||||
fcall_except:
|
||||
UNDEF_RESULT();
|
||||
zend_vm_stack_free_args(call);
|
||||
if (!0) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
goto fcall_end;
|
||||
} else {
|
||||
zend_deprecated_function(fbc);
|
||||
@ -1581,15 +1601,12 @@ fcall_except:
|
||||
zend_execute_ex(call);
|
||||
}
|
||||
} else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) {
|
||||
zval retval;
|
||||
|
||||
call->prev_execute_data = execute_data;
|
||||
EG(current_execute_data) = call;
|
||||
|
||||
if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)
|
||||
&& UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) {
|
||||
UNDEF_RESULT();
|
||||
goto fcall_end;
|
||||
goto fcall_except;
|
||||
}
|
||||
|
||||
ret = 0 ? EX_VAR(opline->result.var) : &retval;
|
||||
@ -1612,15 +1629,13 @@ fcall_except:
|
||||
#endif
|
||||
|
||||
EG(current_execute_data) = execute_data;
|
||||
zend_vm_stack_free_args(call);
|
||||
|
||||
fcall_end:
|
||||
zend_vm_stack_free_args(call);
|
||||
if (!0) {
|
||||
i_zval_ptr_dtor(ret);
|
||||
}
|
||||
|
||||
} else { /* ZEND_OVERLOADED_FUNCTION */
|
||||
zval retval;
|
||||
|
||||
ret = 0 ? EX_VAR(opline->result.var) : &retval;
|
||||
|
||||
call->prev_execute_data = execute_data;
|
||||
@ -1635,7 +1650,6 @@ fcall_except:
|
||||
}
|
||||
}
|
||||
|
||||
fcall_end:
|
||||
if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) {
|
||||
OBJ_RELEASE(Z_OBJ(call->This));
|
||||
}
|
||||
@ -1656,6 +1670,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
|
||||
zend_execute_data *call = EX(call);
|
||||
zend_function *fbc = call->func;
|
||||
zval *ret;
|
||||
zval retval;
|
||||
|
||||
SAVE_OPLINE();
|
||||
EX(call) = call->prev_execute_data;
|
||||
@ -1664,7 +1679,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
|
||||
zend_abstract_method(fbc);
|
||||
fcall_except:
|
||||
UNDEF_RESULT();
|
||||
zend_vm_stack_free_args(call);
|
||||
if (!1) {
|
||||
ret = &retval;
|
||||
ZVAL_UNDEF(ret);
|
||||
}
|
||||
goto fcall_end;
|
||||
} else {
|
||||
zend_deprecated_function(fbc);
|
||||
@ -1695,15 +1713,12 @@ fcall_except:
|
||||
zend_execute_ex(call);
|
||||
}
|
||||
} else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) {
|
||||
zval retval;
|
||||
|
||||
call->prev_execute_data = execute_data;
|
||||
EG(current_execute_data) = call;
|
||||
|
||||
if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)
|
||||
&& UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) {
|
||||
UNDEF_RESULT();
|
||||
goto fcall_end;
|
||||
goto fcall_except;
|
||||
}
|
||||
|
||||
ret = 1 ? EX_VAR(opline->result.var) : &retval;
|
||||
@ -1726,15 +1741,13 @@ fcall_except:
|
||||
#endif
|
||||
|
||||
EG(current_execute_data) = execute_data;
|
||||
zend_vm_stack_free_args(call);
|
||||
|
||||
fcall_end:
|
||||
zend_vm_stack_free_args(call);
|
||||
if (!1) {
|
||||
i_zval_ptr_dtor(ret);
|
||||
}
|
||||
|
||||
} else { /* ZEND_OVERLOADED_FUNCTION */
|
||||
zval retval;
|
||||
|
||||
ret = 1 ? EX_VAR(opline->result.var) : &retval;
|
||||
|
||||
call->prev_execute_data = execute_data;
|
||||
@ -1749,7 +1762,6 @@ fcall_except:
|
||||
}
|
||||
}
|
||||
|
||||
fcall_end:
|
||||
if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) {
|
||||
OBJ_RELEASE(Z_OBJ(call->This));
|
||||
}
|
||||
@ -2810,14 +2822,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z
|
||||
|
||||
EG(current_execute_data) = call->prev_execute_data;
|
||||
|
||||
call_trampoline_end:
|
||||
zend_vm_stack_free_args(call);
|
||||
|
||||
if (ret == &retval) {
|
||||
zval_ptr_dtor(ret);
|
||||
}
|
||||
}
|
||||
|
||||
call_trampoline_end:
|
||||
execute_data = EG(current_execute_data);
|
||||
|
||||
if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) {
|
||||
|
Loading…
Reference in New Issue
Block a user