Skip to content

Commit c45e918

Browse files
committed
Some progress
1 parent 7aa4afc commit c45e918

8 files changed

+61
-16
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Listed silencing a userland function supplementary argument throwing an Exception
3+
--FILE--
4+
<?php
5+
6+
function test1(int $v) {
7+
return $v;
8+
}
9+
10+
function foo() {
11+
throw new Exception();
12+
return 1;
13+
}
14+
15+
try {
16+
$var = test1(@<Exception>foo());
17+
var_dump($var);
18+
} catch (\TypeError $e) {
19+
echo $e->getMessage(), \PHP_EOL;
20+
}
21+
22+
echo "Done\n";
23+
?>
24+
--EXPECTF--
25+
test1(): Argument #1 ($v) must be of type int, null given, called in %s on line %d
26+
Done

Zend/zend_execute.c

+8
Original file line numberDiff line numberDiff line change
@@ -4095,10 +4095,13 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o
40954095
/* Do not cleanup unfinished calls for SILENCE live range as it might still get executed
40964096
* However, this can only happen if the exception is an instance of Exception
40974097
* (Error never gets suppressed) */
4098+
/*
40984099
if (UNEXPECTED(is_in_silence_live_range(EX(func)->op_array, op_num)
40994100
&& instanceof_function(zend_ce_exception, EG(exception)->ce))) {
41004101
return;
41014102
}
4103+
*/
4104+
bool is_silence = is_in_silence_live_range(EX(func)->op_array, op_num) && instanceof_function(zend_ce_exception, EG(exception)->ce);
41024105
zend_execute_data *call = EX(call);
41034106
zend_op *opline = EX(func)->op_array.opcodes + op_num;
41044107
int level;
@@ -4170,9 +4173,14 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o
41704173
}
41714174
break;
41724175
}
4176+
41734177
if (!do_exit) {
41744178
opline--;
41754179
}
4180+
/* If this a silence range we should only release the last arg */
4181+
if (is_silence) {
4182+
return;
4183+
}
41764184
} while (!do_exit);
41774185
if (call->prev_execute_data) {
41784186
/* skip current call region */

Zend/zend_vm_def.h

+7
Original file line numberDiff line numberDiff line change
@@ -7518,12 +7518,19 @@ ZEND_VM_HANDLER(203, ZEND_SILENCE_CATCH, ANY, ANY)
75187518
/* Set value to NULL */
75197519
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
75207520
/* Make internal functions which set a return value early return false */
7521+
/*
75217522
if (UNEXPECTED(Z_TYPE_P(EX_VAR(opline->result.var)) != IS_UNDEF
75227523
&& Z_TYPE_P(EX_VAR(opline->result.var)) <= IS_TRUE)) {
75237524
ZVAL_FALSE(EX_VAR(opline->result.var));
75247525
} else {
75257526
ZVAL_NULL(EX_VAR(opline->result.var));
75267527
}
7528+
*/
7529+
7530+
/* Set return value to null, except when an internal function has set a return value */
7531+
if (EXPECTED(Z_TYPE_P(EX_VAR(opline->result.var)) == IS_UNDEF)) {
7532+
ZVAL_NULL(EX_VAR(opline->result.var));
7533+
}
75277534
}
75287535
}
75297536

Zend/zend_vm_execute.h

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/zend_test/test.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "zend_interfaces.h"
3030
#include "zend_weakrefs.h"
3131
#include "Zend/Optimizer/zend_optimizer.h"
32+
#include "zend_exceptions.h"
3233
#include "test_arginfo.h"
3334

3435
ZEND_DECLARE_MODULE_GLOBALS(zend_test)
@@ -438,21 +439,21 @@ static ZEND_FUNCTION(zend_suppress_exception_internal_return_false)
438439
ZEND_PARSE_PARAMETERS_NONE();
439440

440441
RETVAL_FALSE;
441-
zend_throw_error(NULL, "Shouldn't be seen");
442+
zend_throw_exception(NULL, "Shouldn't be seen", 0);
442443
}
443444
static ZEND_FUNCTION(zend_suppress_exception_internal_return_true)
444445
{
445446
ZEND_PARSE_PARAMETERS_NONE();
446447

447448
RETVAL_TRUE;
448-
zend_throw_error(NULL, "Shouldn't be seen");
449+
zend_throw_exception(NULL, "Shouldn't be seen", 0);
449450
}
450451
static ZEND_FUNCTION(zend_suppress_exception_internal_return_int)
451452
{
452453
ZEND_PARSE_PARAMETERS_NONE();
453454

454455
RETVAL_LONG(20);
455-
zend_throw_error(NULL, "Shouldn't be seen");
456+
zend_throw_exception(NULL, "Shouldn't be seen", 0);
456457
}
457458

458459
static zend_object *zend_test_class_new(zend_class_entry *class_type)

ext/zend_test/tests/suppress_exception_internal_return_false.phpt

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
--TEST--
22
Suppresion operator internal functions can return things other than null: false
3-
--SKIPIF--
4-
<?php if (!extension_loaded('zend_test')) die('skip: zend_test extension required'); ?>
3+
--EXTENSIONS--
4+
zend_test
55
--FILE--
66
<?php
77

@@ -19,5 +19,5 @@ echo 'Done', PHP_EOL;
1919
?>
2020
--EXPECT--
2121
bool(false)
22-
Error: Shouldn't be seen
22+
Exception: Shouldn't be seen
2323
Done

ext/zend_test/tests/suppress_exception_internal_return_int.phpt

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
--TEST--
22
Suppresion operator internal functions can return things other than null: int
3-
--SKIPIF--
4-
<?php if (!extension_loaded('zend_test')) die('skip: zend_test extension required'); ?>
5-
--XFAIL--
6-
TBD if should return false, null, or int
3+
--EXTENSIONS--
4+
zend_test
75
--FILE--
86
<?php
97

@@ -21,5 +19,5 @@ echo 'Done', PHP_EOL;
2119
?>
2220
--EXPECT--
2321
int(20)
24-
Error: Shouldn't be seen
22+
Exception: Shouldn't be seen
2523
Done

ext/zend_test/tests/suppress_exception_internal_return_true.phpt

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
--TEST--
22
Suppresion operator internal functions can return things other than null: true
3-
--SKIPIF--
4-
<?php if (!extension_loaded('zend_test')) die('skip: zend_test extension required'); ?>
5-
--XFAIL--
6-
TBD if should return false, null, or true
3+
--EXTENSIONS--
4+
zend_test
75
--FILE--
86
<?php
97

@@ -21,5 +19,5 @@ echo 'Done', PHP_EOL;
2119
?>
2220
--EXPECT--
2321
bool(true)
24-
Error: Shouldn't be seen
22+
Exception: Shouldn't be seen
2523
Done

0 commit comments

Comments
 (0)