Skip to content

Commit 2114867

Browse files
committed
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.
1 parent 68b26ff commit 2114867

File tree

7 files changed

+46
-10
lines changed

7 files changed

+46
-10
lines changed

Zend/tests/exception_017.phpt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ C::foo();
3030
--EXPECTF--
3131
Exception: Cannot call abstract method C::foo() in %sexception_017.php on line %d
3232

33-
Exception: Argument 1 passed to foo() must be callable, string given, called in %sexception_017.php on line %d
34-
Exception: Cannot call abstract method C::foo()
33+
Exception: Argument 1 passed to foo() must be callable, string given, called in %s on line %d
3534

3635
Fatal error: Uncaught Error: Cannot call abstract method C::foo() in %sexception_017.php:%d
3736
Stack trace:
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
A "non well formed" notice converted to exception should result in a ZPP failure
3+
--FILE--
4+
<?php
5+
6+
set_error_handler(function($_, $msg) {
7+
throw new Exception($msg);
8+
}, E_NOTICE);
9+
10+
try {
11+
wordwrap("foo", "123foo", "");
12+
} catch (Exception $e) {
13+
echo $e, "\n";
14+
}
15+
16+
?>
17+
--EXPECTF--
18+
Exception: A non well formed numeric value encountered in %s:%d
19+
Stack trace:
20+
#0 [internal function]: {closure}(%s)
21+
#1 %s(%d): wordwrap('foo', '123foo', '')
22+
#2 {main}

Zend/zend_API.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,9 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_long_weak(zval *arg, zend_long *dest)
438438
return 0;
439439
}
440440
}
441+
if (UNEXPECTED(EG(exception))) {
442+
return 0;
443+
}
441444
} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
442445
*dest = 0;
443446
} 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
479482
return 0;
480483
}
481484
}
485+
if (UNEXPECTED(EG(exception))) {
486+
return 0;
487+
}
482488
} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
483489
*dest = 0;
484490
} 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) /
514520
return 0;
515521
}
516522
}
523+
if (UNEXPECTED(EG(exception))) {
524+
return 0;
525+
}
517526
} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
518527
*dest = 0.0;
519528
} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
@@ -3163,12 +3172,9 @@ static zend_always_inline int zend_is_callable_check_func(int check_flags, zval
31633172
if (retval) {
31643173
if (fcc->calling_scope && !call_via_handler) {
31653174
if (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT) {
3175+
retval = 0;
31663176
if (error) {
31673177
zend_spprintf(error, 0, "cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3168-
retval = 0;
3169-
} else {
3170-
zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3171-
retval = 0;
31723178
}
31733179
} else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
31743180
int severity;

Zend/zend_execute.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,12 @@ static ZEND_COLD void zend_verify_arg_error(
792792
const char *fname, *fsep, *fclass;
793793
const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind;
794794

795+
if (EG(exception)) {
796+
/* The type verification itself might have already thrown an exception
797+
* through a promoted warning. */
798+
return;
799+
}
800+
795801
if (value) {
796802
zend_verify_type_error_common(
797803
zf, arg_info, ce, value,

Zend/zend_operators.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3131,6 +3131,9 @@ ZEND_API zend_uchar ZEND_FASTCALL _is_numeric_string_ex(const char *str, size_t
31313131
}
31323132
if (allow_errors == -1) {
31333133
zend_error(E_NOTICE, "A non well formed numeric value encountered");
3134+
if (EG(exception)) {
3135+
return 0;
3136+
}
31343137
}
31353138
}
31363139

Zend/zend_vm_def.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5209,7 +5209,7 @@ ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED|CACHE_SLOT)
52095209
zval *param = EX_VAR(opline->result.var);
52105210

52115211
SAVE_OPLINE();
5212-
if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)) || EG(exception))) {
5212+
if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)))) {
52135213
HANDLE_EXCEPTION();
52145214
}
52155215
}
@@ -5257,7 +5257,7 @@ ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST, CACHE_SLOT)
52575257
zval *default_value = RT_CONSTANT(opline, opline->op2);
52585258

52595259
SAVE_OPLINE();
5260-
if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)) || EG(exception))) {
5260+
if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)))) {
52615261
HANDLE_EXCEPTION();
52625262
}
52635263
}

Zend/zend_vm_execute.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3060,7 +3060,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CON
30603060
zval *default_value = RT_CONSTANT(opline, opline->op2);
30613061

30623062
SAVE_OPLINE();
3063-
if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)) || EG(exception))) {
3063+
if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)))) {
30643064
HANDLE_EXCEPTION();
30653065
}
30663066
}
@@ -3139,7 +3139,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_UNUSED_H
31393139
zval *param = EX_VAR(opline->result.var);
31403140

31413141
SAVE_OPLINE();
3142-
if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)) || EG(exception))) {
3142+
if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)))) {
31433143
HANDLE_EXCEPTION();
31443144
}
31453145
}

0 commit comments

Comments
 (0)