mirror of
https://github.com/php/php-src.git
synced 2024-11-23 09:54:15 +08:00
Fix handling of throwing undef var in verify return
If we have an undefined variable and null is not accepted by the return type, we want to throw just the undef var error. In this case this lead to an infinite loop, because we overwrite the exception opline in SAVE_OPLINE and it does not get reset when chaining into a previous exception. Add an assertiong to catch this case earlier.
This commit is contained in:
parent
8c68745f43
commit
1748b8111e
23
Zend/tests/undef_var_in_verify_return.phpt
Normal file
23
Zend/tests/undef_var_in_verify_return.phpt
Normal file
@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
Throwing undef var in verify return
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
set_error_handler(function(int $severity, string $message, string $filename, int $lineNumber): void {
|
||||
throw new ErrorException($message, 0, $severity, $filename, $lineNumber);
|
||||
});
|
||||
|
||||
function test(): string {
|
||||
return $test;
|
||||
}
|
||||
|
||||
test();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught ErrorException: Undefined variable $test in %s:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): {closure}(2, 'Undefined varia...', '%s', 8)
|
||||
#1 %s(%d): test()
|
||||
#2 {main}
|
||||
thrown in %s on line %d
|
@ -144,6 +144,13 @@ void zend_exception_restore(void) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_always_inline zend_bool is_handle_exception_set() {
|
||||
zend_execute_data *execute_data = EG(current_execute_data);
|
||||
return !execute_data->func
|
||||
|| !ZEND_USER_CODE(execute_data->func->common.type)
|
||||
|| execute_data->opline->opcode == ZEND_HANDLE_EXCEPTION;
|
||||
}
|
||||
|
||||
ZEND_API ZEND_COLD void zend_throw_exception_internal(zend_object *exception) /* {{{ */
|
||||
{
|
||||
#ifdef HAVE_DTRACE
|
||||
@ -161,6 +168,7 @@ ZEND_API ZEND_COLD void zend_throw_exception_internal(zend_object *exception) /*
|
||||
zend_exception_set_previous(exception, EG(exception));
|
||||
EG(exception) = exception;
|
||||
if (previous) {
|
||||
ZEND_ASSERT(is_handle_exception_set() && "HANDLE_EXCEPTION not set?");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -179,9 +187,7 @@ ZEND_API ZEND_COLD void zend_throw_exception_internal(zend_object *exception) /*
|
||||
zend_throw_exception_hook(exception);
|
||||
}
|
||||
|
||||
if (!EG(current_execute_data)->func ||
|
||||
!ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
|
||||
EG(current_execute_data)->opline->opcode == ZEND_HANDLE_EXCEPTION) {
|
||||
if (is_handle_exception_set()) {
|
||||
/* no need to rethrow the exception */
|
||||
return;
|
||||
}
|
||||
|
@ -4195,8 +4195,11 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV
|
||||
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) {
|
||||
SAVE_OPLINE();
|
||||
retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1();
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) {
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9707,8 +9707,11 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP
|
||||
if (IS_CONST == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) {
|
||||
SAVE_OPLINE();
|
||||
retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1();
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) {
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
}
|
||||
|
||||
@ -20051,8 +20054,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN
|
||||
if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) {
|
||||
SAVE_OPLINE();
|
||||
retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1();
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) {
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
}
|
||||
|
||||
@ -27656,8 +27662,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN
|
||||
if (IS_VAR == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) {
|
||||
SAVE_OPLINE();
|
||||
retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1();
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) {
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
}
|
||||
|
||||
@ -34853,8 +34862,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED
|
||||
if (IS_UNUSED == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) {
|
||||
SAVE_OPLINE();
|
||||
retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1();
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) {
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
}
|
||||
|
||||
@ -46545,8 +46557,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU
|
||||
if (IS_CV == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) {
|
||||
SAVE_OPLINE();
|
||||
retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1();
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) {
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user