Skip to content

Commit eb714c2

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

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
@@ -7320,8 +7320,6 @@ ZEND_VM_HANDLER(201, ZEND_SILENCE_CATCH, ANY, ANY)
73207320

73217321
SAVE_OPLINE();
73227322

7323-
zend_exception_restore();
7324-
73257323
/* Came from class list virtual catch blocks */
73267324
if (opline->extended_value == 2) {
73277325
if (EG(exception) == NULL) {
@@ -7339,6 +7337,13 @@ ZEND_VM_HANDLER(201, ZEND_SILENCE_CATCH, ANY, ANY)
73397337
HANDLE_EXCEPTION();
73407338
}
73417339
} else if (EG(exception) && opline->extended_value != 2) {
7340+
ZEND_ASSERT(EG(exception)->ce);
7341+
/* Only suppress Exception or a subclass of, and NOT Error throwable errors */
7342+
if (!instanceof_function(zend_ce_exception, EG(exception)->ce)) {
7343+
zend_rethrow_exception(execute_data);
7344+
HANDLE_EXCEPTION();
7345+
}
7346+
73427347
#ifdef HAVE_DTRACE
73437348
if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) {
73447349
DTRACE_EXCEPTION_CAUGHT((char *)EG(exception)->ce->name);
@@ -7826,8 +7831,11 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
78267831
}
78277832
}
78287833

7829-
/* Do not cleanup unfinished calls for SILENCE live range as it might still get executed */
7830-
if (!is_in_silence_live_range(EX(func)->op_array, throw_op_num)) {
7834+
/* Do not cleanup unfinished calls for SILENCE live range as it might still get executed
7835+
* However, this can only happen if the exception is an instance of Exception
7836+
* (Error never gets suppressed) */
7837+
if (!is_in_silence_live_range(EX(func)->op_array, throw_op_num)
7838+
|| !instanceof_function(zend_ce_exception, EG(exception)->ce)) {
78317839
cleanup_unfinished_calls(execute_data, throw_op_num);
78327840
}
78337841

Zend/zend_vm_execute.h

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

27592759
SAVE_OPLINE();
27602760

2761-
zend_exception_restore();
2762-
27632761
/* Came from class list virtual catch blocks */
27642762
if (opline->extended_value == 2) {
27652763
if (EG(exception) == NULL) {
@@ -2777,6 +2775,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SILENCE_CATCH_SPEC_HANDLER(ZEN
27772775
HANDLE_EXCEPTION();
27782776
}
27792777
} else if (EG(exception) && opline->extended_value != 2) {
2778+
ZEND_ASSERT(EG(exception)->ce);
2779+
/* Only suppress Exception or a subclass of, and NOT Error throwable errors */
2780+
if (!instanceof_function(zend_ce_exception, EG(exception)->ce)) {
2781+
zend_rethrow_exception(execute_data);
2782+
HANDLE_EXCEPTION();
2783+
}
2784+
27802785
#ifdef HAVE_DTRACE
27812786
if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) {
27822787
DTRACE_EXCEPTION_CAUGHT((char *)EG(exception)->ce->name);
@@ -3018,8 +3023,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(
30183023
}
30193024
}
30203025

3021-
/* Do not cleanup unfinished calls for SILENCE live range as it might still get executed */
3022-
if (!is_in_silence_live_range(EX(func)->op_array, throw_op_num)) {
3026+
/* Do not cleanup unfinished calls for SILENCE live range as it might still get executed
3027+
* However, this can only happen if the exception is an instance of Exception
3028+
* (Error never gets suppressed) */
3029+
if (!is_in_silence_live_range(EX(func)->op_array, throw_op_num)
3030+
|| !instanceof_function(zend_ce_exception, EG(exception)->ce)) {
30233031
cleanup_unfinished_calls(execute_data, throw_op_num);
30243032
}
30253033

0 commit comments

Comments
 (0)