Skip to content

Commit 4087ca2

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 04938fe commit 4087ca2

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
@@ -9332,6 +9332,7 @@ static void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
93329332
{
93339333
zend_ast *expr_ast = ast->child[0];
93349334
znode silence_node;
9335+
zend_op *silence_start_op;
93359336
zend_op *silence_catch_op;
93369337
uint32_t try_catch_offset;
93379338
uint32_t virtual_catch_op_num;
@@ -9341,7 +9342,7 @@ static void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
93419342
try_catch_offset = zend_add_try_element(get_next_op_number());
93429343
CG(context).try_catch_offset = try_catch_offset;
93439344

9344-
zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
9345+
silence_start_op = zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
93459346

93469347
if (expr_ast->kind == ZEND_AST_VAR) {
93479348
/* For @$var we need to force a FETCH instruction, otherwise the CV access will
@@ -9368,7 +9369,8 @@ static void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
93689369
zend_ast_list *classes = zend_ast_get_list(ast->child[1]);
93699370
uint32_t opnum_catch = (uint32_t)-1;
93709371

9371-
/* Inform SILENCE_CATCH opcode that there is an exception class list */
9372+
/* Inform SILENCE_START and SILENCE_CATCH opcode that there is an exception class list */
9373+
silence_start_op->extended_value = 1;
93729374
silence_catch_op->extended_value = 2;
93739375

93749376
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
@@ -7434,6 +7434,11 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
74347434

74357435
ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting));
74367436

7437+
/* Do not suppress diagnostics when a class list is passed to @ */
7438+
if (opline->extended_value == 1) {
7439+
ZEND_VM_NEXT_OPCODE();
7440+
}
7441+
74377442
if (!E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))) {
74387443
do {
74397444
/* Do not silence fatal errors */
@@ -7481,20 +7486,15 @@ ZEND_VM_HANDLER(203, ZEND_SILENCE_CATCH, ANY, ANY)
74817486

74827487
/* Came from class list virtual catch blocks */
74837488
if (opline->extended_value == 2) {
7484-
if (EG(exception) == NULL) {
7485-
/* Free object (needed to not leak memory on @new) */
7486-
if (Z_TYPE_P(EX_VAR(opline->result.var)) == IS_OBJECT) {
7487-
//OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
7488-
}
7489-
7490-
/* Set value to NULL */
7491-
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
7492-
ZVAL_NULL(EX_VAR(opline->result.var));
7493-
}
7494-
} else {
7489+
if (EG(exception) != NULL) {
74957490
zend_rethrow_exception(execute_data);
74967491
HANDLE_EXCEPTION();
74977492
}
7493+
/* Result is UNDEF means an exception has been caught */
7494+
if (opline->result_type & (IS_VAR | IS_TMP_VAR)
7495+
&& Z_TYPE_P(EX_VAR(opline->result.var)) == IS_UNDEF) {
7496+
ZVAL_NULL(EX_VAR(opline->result.var));
7497+
}
74987498
} else if (EG(exception) && opline->extended_value != 2) {
74997499
ZEND_ASSERT(EG(exception)->ce);
75007500
/* Only suppress Exception or a subclass of, and NOT Error throwable errors */

Zend/zend_vm_execute.h

Lines changed: 11 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)