From: Nikita Popov Date: Tue, 8 Oct 2019 14:53:23 +0000 (+0200) Subject: Handle "non well formed" exception during ZPP X-Git-Tag: php-7.4.0RC4~32 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=21148679d1dfb614404c09a918d9d2b74f120640;p=php Handle "non well formed" exception during ZPP Previously if the "non well formed" notice was converted into an exception we'd still end up executing the function. Also drop the now unnecessary EG(exception) checks in the engine. Additionally remote a bogus exception in zend_is_callable: It should only be writing to error, but not directly throwing. --- diff --git a/Zend/tests/exception_017.phpt b/Zend/tests/exception_017.phpt index f980b297fb..8d87ec6ee9 100644 --- a/Zend/tests/exception_017.phpt +++ b/Zend/tests/exception_017.phpt @@ -30,8 +30,7 @@ C::foo(); --EXPECTF-- Exception: Cannot call abstract method C::foo() in %sexception_017.php on line %d -Exception: Argument 1 passed to foo() must be callable, string given, called in %sexception_017.php on line %d -Exception: Cannot call abstract method C::foo() +Exception: Argument 1 passed to foo() must be callable, string given, called in %s on line %d Fatal error: Uncaught Error: Cannot call abstract method C::foo() in %sexception_017.php:%d Stack trace: diff --git a/Zend/tests/non_well_formed_param_exception.phpt b/Zend/tests/non_well_formed_param_exception.phpt new file mode 100644 index 0000000000..d688375f9f --- /dev/null +++ b/Zend/tests/non_well_formed_param_exception.phpt @@ -0,0 +1,22 @@ +--TEST-- +A "non well formed" notice converted to exception should result in a ZPP failure +--FILE-- + +--EXPECTF-- +Exception: A non well formed numeric value encountered in %s:%d +Stack trace: +#0 [internal function]: {closure}(%s) +#1 %s(%d): wordwrap('foo', '123foo', '') +#2 {main} diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 5be9d94dee..3fef3733f7 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -438,6 +438,9 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_long_weak(zval *arg, zend_long *dest) return 0; } } + if (UNEXPECTED(EG(exception))) { + return 0; + } } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) { *dest = 0; } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) { @@ -479,6 +482,9 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *de return 0; } } + if (UNEXPECTED(EG(exception))) { + return 0; + } } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) { *dest = 0; } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) { @@ -514,6 +520,9 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_double_weak(zval *arg, double *dest) / return 0; } } + if (UNEXPECTED(EG(exception))) { + return 0; + } } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) { *dest = 0.0; } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) { @@ -3163,12 +3172,9 @@ get_function_via_handler: if (retval) { if (fcc->calling_scope && !call_via_handler) { if (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT) { + retval = 0; if (error) { zend_spprintf(error, 0, "cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name)); - retval = 0; - } else { - zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name)); - retval = 0; } } else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) { int severity; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 15f3ee792a..015ee8990f 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -792,6 +792,12 @@ static ZEND_COLD void zend_verify_arg_error( const char *fname, *fsep, *fclass; const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind; + if (EG(exception)) { + /* The type verification itself might have already thrown an exception + * through a promoted warning. */ + return; + } + if (value) { zend_verify_type_error_common( zf, arg_info, ce, value, diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 840ee75a41..7c0c569164 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -3131,6 +3131,9 @@ process_double: } if (allow_errors == -1) { zend_error(E_NOTICE, "A non well formed numeric value encountered"); + if (EG(exception)) { + return 0; + } } } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 7c102073a3..649b07d36e 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5209,7 +5209,7 @@ ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED|CACHE_SLOT) zval *param = EX_VAR(opline->result.var); SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)) || EG(exception))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)))) { HANDLE_EXCEPTION(); } } @@ -5257,7 +5257,7 @@ ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST, CACHE_SLOT) zval *default_value = RT_CONSTANT(opline, opline->op2); SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)) || EG(exception))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)))) { HANDLE_EXCEPTION(); } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 4cd21c0e61..b4a59dff0e 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3060,7 +3060,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CON zval *default_value = RT_CONSTANT(opline, opline->op2); SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)) || EG(exception))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)))) { HANDLE_EXCEPTION(); } } @@ -3139,7 +3139,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_UNUSED_H zval *param = EX_VAR(opline->result.var); SAVE_OPLINE(); - if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)) || EG(exception))) { + if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)))) { HANDLE_EXCEPTION(); } }