Skip to content

Commit b941f1f

Browse files
committed
Only suppres instances of Exception and not Throwable by default
1 parent c2eb689 commit b941f1f

File tree

6 files changed

+74
-12
lines changed

6 files changed

+74
-12
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Listing Error in silence throwable class list should suppress
3+
--FILE--
4+
<?php
5+
6+
function test1() {
7+
throw new Error();
8+
return true;
9+
}
10+
11+
$var = @<Error>test1();
12+
13+
var_dump($var);
14+
15+
echo "Done\n";
16+
?>
17+
--EXPECT--
18+
NULL
19+
Done

Zend/tests/silence_operator/silence_function_nested.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function test2($a) {
1313
return test1();
1414
}
1515

16-
$var = @test2();
16+
$var = @test2(1);
1717

1818
var_dump($var);
1919

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Suppression operator must not suppres Error type Throwable errors
3+
--FILE--
4+
<?php
5+
6+
function test1() {
7+
throw new Error();
8+
return true;
9+
}
10+
11+
$var = @test1();
12+
13+
var_dump($var);
14+
15+
echo "Done\n";
16+
?>
17+
--EXPECTF--
18+
Fatal error: Uncaught Error in %s:4
19+
Stack trace:
20+
#0 %s(8): test1()
21+
#1 {main}
22+
thrown in %s on line 4

Zend/tests/silence_operator/yield_from_silenced_non_iterable.phpt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ function foo() {
99

1010
function generator() {
1111
yield 1;
12+
/* This emits a Error type of throwable which is not suppressed */
1213
@yield from foo();
1314
yield 2;
1415
}
@@ -19,7 +20,11 @@ foreach (generator() as $val) {
1920

2021
echo "Done\n";
2122
?>
22-
--EXPECT--
23+
--EXPECTF--
2324
int(1)
24-
int(2)
25-
Done
25+
26+
Fatal error: Uncaught Error: Can use "yield from" only with arrays and Traversables in %s:%d
27+
Stack trace:
28+
#0 %s(%d): generator()
29+
#1 {main}
30+
thrown in %s on line %d

Zend/zend_vm_def.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7395,8 +7395,6 @@ ZEND_VM_HANDLER(203, ZEND_SILENCE_CATCH, ANY, ANY)
73957395

73967396
SAVE_OPLINE();
73977397

7398-
zend_exception_restore();
7399-
74007398
/* Came from class list virtual catch blocks */
74017399
if (opline->extended_value == 2) {
74027400
if (EG(exception) == NULL) {
@@ -7414,6 +7412,13 @@ ZEND_VM_HANDLER(203, ZEND_SILENCE_CATCH, ANY, ANY)
74147412
HANDLE_EXCEPTION();
74157413
}
74167414
} else if (EG(exception) && opline->extended_value != 2) {
7415+
ZEND_ASSERT(EG(exception)->ce);
7416+
/* Only suppress Exception or a subclass of, and NOT Error throwable errors */
7417+
if (!instanceof_function(zend_ce_exception, EG(exception)->ce)) {
7418+
zend_rethrow_exception(execute_data);
7419+
HANDLE_EXCEPTION();
7420+
}
7421+
74177422
#ifdef HAVE_DTRACE
74187423
if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) {
74197424
DTRACE_EXCEPTION_CAUGHT((char *)EG(exception)->ce->name);
@@ -7876,8 +7881,11 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
78767881
}
78777882
}
78787883

7879-
/* Do not cleanup unfinished calls for SILENCE live range as it might still get executed */
7880-
if (!is_in_silence_live_range(EX(func)->op_array, throw_op_num)) {
7884+
/* Do not cleanup unfinished calls for SILENCE live range as it might still get executed
7885+
* However, this can only happen if the exception is an instance of Exception
7886+
* (Error never gets suppressed) */
7887+
if (!is_in_silence_live_range(EX(func)->op_array, throw_op_num)
7888+
|| !instanceof_function(zend_ce_exception, EG(exception)->ce)) {
78817889
cleanup_unfinished_calls(execute_data, throw_op_num);
78827890
}
78837891

Zend/zend_vm_execute.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2898,8 +2898,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SILENCE_CATCH_SPEC_HANDLER(ZEN
28982898

28992899
SAVE_OPLINE();
29002900

2901-
zend_exception_restore();
2902-
29032901
/* Came from class list virtual catch blocks */
29042902
if (opline->extended_value == 2) {
29052903
if (EG(exception) == NULL) {
@@ -2917,6 +2915,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SILENCE_CATCH_SPEC_HANDLER(ZEN
29172915
HANDLE_EXCEPTION();
29182916
}
29192917
} else if (EG(exception) && opline->extended_value != 2) {
2918+
ZEND_ASSERT(EG(exception)->ce);
2919+
/* Only suppress Exception or a subclass of, and NOT Error throwable errors */
2920+
if (!instanceof_function(zend_ce_exception, EG(exception)->ce)) {
2921+
zend_rethrow_exception(execute_data);
2922+
HANDLE_EXCEPTION();
2923+
}
2924+
29202925
#ifdef HAVE_DTRACE
29212926
if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) {
29222927
DTRACE_EXCEPTION_CAUGHT((char *)EG(exception)->ce->name);
@@ -3144,8 +3149,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(
31443149
}
31453150
}
31463151

3147-
/* Do not cleanup unfinished calls for SILENCE live range as it might still get executed */
3148-
if (!is_in_silence_live_range(EX(func)->op_array, throw_op_num)) {
3152+
/* Do not cleanup unfinished calls for SILENCE live range as it might still get executed
3153+
* However, this can only happen if the exception is an instance of Exception
3154+
* (Error never gets suppressed) */
3155+
if (!is_in_silence_live_range(EX(func)->op_array, throw_op_num)
3156+
|| !instanceof_function(zend_ce_exception, EG(exception)->ce)) {
31493157
cleanup_unfinished_calls(execute_data, throw_op_num);
31503158
}
31513159

0 commit comments

Comments
 (0)