Skip to content

Commit 0ba8a9a

Browse files
committed
Do not suppress diagnostics when a class list is passed to silence
Also fixes a bug where any return value from @<class> would be NULL
1 parent b941f1f commit 0ba8a9a

File tree

5 files changed

+66
-24
lines changed

5 files changed

+66
-24
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Diagnostics should still be emitted if a class list is passed to @, userland
3+
--FILE--
4+
<?php
5+
6+
function test() {
7+
trigger_error('Diagnostic message', E_USER_NOTICE);
8+
return true;
9+
}
10+
11+
$var = @<Exception>test();
12+
13+
var_dump($var);
14+
15+
echo "Done\n";
16+
?>
17+
--EXPECTF--
18+
Notice: Diagnostic message in %s on line %d
19+
bool(true)
20+
Done
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Diagnostics should still be emitted if a class list is passed to @, internal
3+
--FILE--
4+
<?php
5+
6+
function test() {
7+
$r = $a + 1;
8+
return $r;
9+
}
10+
11+
$var = @<Exception>test();
12+
13+
var_dump($var);
14+
15+
echo "Done\n";
16+
?>
17+
--EXPECTF--
18+
Warning: Undefined variable $a in %s on line %d
19+
int(1)
20+
Done

Zend/zend_compile.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9242,6 +9242,7 @@ static void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
92429242
{
92439243
zend_ast *expr_ast = ast->child[0];
92449244
znode silence_node;
9245+
zend_op *silence_start_op;
92459246
zend_op *silence_catch_op;
92469247
uint32_t try_catch_offset;
92479248
uint32_t virtual_catch_op_num;
@@ -9251,7 +9252,7 @@ static void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
92519252
try_catch_offset = zend_add_try_element(get_next_op_number());
92529253
CG(context).try_catch_offset = try_catch_offset;
92539254

9254-
zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
9255+
silence_start_op = zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
92559256

92569257
if (expr_ast->kind == ZEND_AST_VAR) {
92579258
/* For @$var we need to force a FETCH instruction, otherwise the CV access will
@@ -9278,7 +9279,8 @@ static void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
92789279
zend_ast_list *classes = zend_ast_get_list(ast->child[1]);
92799280
uint32_t opnum_catch = (uint32_t)-1;
92809281

9281-
/* Inform SILENCE_CATCH opcode that there is an exception class list */
9282+
/* Inform SILENCE_START and SILENCE_CATCH opcode that there is an exception class list */
9283+
silence_start_op->extended_value = 1;
92829284
silence_catch_op->extended_value = 2;
92839285

92849286
ZEND_ASSERT(classes->children > 0 && "Should have at least one class");

Zend/zend_vm_def.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7350,6 +7350,11 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
73507350

73517351
ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting));
73527352

7353+
/* Do not suppress diagnostics when a class list is passed to @ */
7354+
if (opline->extended_value == 1) {
7355+
ZEND_VM_NEXT_OPCODE();
7356+
}
7357+
73537358
if (!E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))) {
73547359
do {
73557360
/* Do not silence fatal errors */
@@ -7397,20 +7402,15 @@ ZEND_VM_HANDLER(203, ZEND_SILENCE_CATCH, ANY, ANY)
73977402

73987403
/* Came from class list virtual catch blocks */
73997404
if (opline->extended_value == 2) {
7400-
if (EG(exception) == NULL) {
7401-
/* Free object (needed to not leak memory on @new) */
7402-
if (Z_TYPE_P(EX_VAR(opline->result.var)) == IS_OBJECT) {
7403-
//OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
7404-
}
7405-
7406-
/* Set value to NULL */
7407-
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
7408-
ZVAL_NULL(EX_VAR(opline->result.var));
7409-
}
7410-
} else {
7405+
if (EG(exception) != NULL) {
74117406
zend_rethrow_exception(execute_data);
74127407
HANDLE_EXCEPTION();
74137408
}
7409+
/* Result is UNDEF means an exception has been caught */
7410+
if (opline->result_type & (IS_VAR | IS_TMP_VAR)
7411+
&& Z_TYPE_P(EX_VAR(opline->result.var)) == IS_UNDEF) {
7412+
ZVAL_NULL(EX_VAR(opline->result.var));
7413+
}
74147414
} else if (EG(exception) && opline->extended_value != 2) {
74157415
ZEND_ASSERT(EG(exception)->ce);
74167416
/* Only suppress Exception or a subclass of, and NOT Error throwable errors */

Zend/zend_vm_execute.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2864,6 +2864,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEN
28642864

28652865
ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting));
28662866

2867+
/* Do not suppress diagnostics when a class list is passed to @ */
2868+
if (opline->extended_value == 1) {
2869+
ZEND_VM_NEXT_OPCODE();
2870+
}
2871+
28672872
if (!E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))) {
28682873
do {
28692874
/* Do not silence fatal errors */
@@ -2900,20 +2905,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SILENCE_CATCH_SPEC_HANDLER(ZEN
29002905

29012906
/* Came from class list virtual catch blocks */
29022907
if (opline->extended_value == 2) {
2903-
if (EG(exception) == NULL) {
2904-
/* Free object (needed to not leak memory on @new) */
2905-
if (Z_TYPE_P(EX_VAR(opline->result.var)) == IS_OBJECT) {
2906-
//OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
2907-
}
2908-
2909-
/* Set value to NULL */
2910-
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
2911-
ZVAL_NULL(EX_VAR(opline->result.var));
2912-
}
2913-
} else {
2908+
if (EG(exception) != NULL) {
29142909
zend_rethrow_exception(execute_data);
29152910
HANDLE_EXCEPTION();
29162911
}
2912+
/* Result is UNDEF means an exception has been caught */
2913+
if (opline->result_type & (IS_VAR | IS_TMP_VAR)
2914+
&& Z_TYPE_P(EX_VAR(opline->result.var)) == IS_UNDEF) {
2915+
ZVAL_NULL(EX_VAR(opline->result.var));
2916+
}
29172917
} else if (EG(exception) && opline->extended_value != 2) {
29182918
ZEND_ASSERT(EG(exception)->ce);
29192919
/* Only suppress Exception or a subclass of, and NOT Error throwable errors */

0 commit comments

Comments
 (0)