Skip to content

Commit e39218f

Browse files
committed
Some progress
1 parent ec099be commit e39218f

8 files changed

+61
-16
lines changed
Lines changed: 26 additions & 0 deletions
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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3901,10 +3901,13 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o
39013901
/* Do not cleanup unfinished calls for SILENCE live range as it might still get executed
39023902
* However, this can only happen if the exception is an instance of Exception
39033903
* (Error never gets suppressed) */
3904+
/*
39043905
if (UNEXPECTED(is_in_silence_live_range(EX(func)->op_array, op_num)
39053906
&& instanceof_function(zend_ce_exception, EG(exception)->ce))) {
39063907
return;
39073908
}
3909+
*/
3910+
bool is_silence = is_in_silence_live_range(EX(func)->op_array, op_num) && instanceof_function(zend_ce_exception, EG(exception)->ce);
39083911
zend_execute_data *call = EX(call);
39093912
zend_op *opline = EX(func)->op_array.opcodes + op_num;
39103913
int level;
@@ -3976,9 +3979,14 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o
39763979
}
39773980
break;
39783981
}
3982+
39793983
if (!do_exit) {
39803984
opline--;
39813985
}
3986+
/* If this a silence range we should only release the last arg */
3987+
if (is_silence) {
3988+
return;
3989+
}
39823990
} while (!do_exit);
39833991
if (call->prev_execute_data) {
39843992
/* skip current call region */

Zend/zend_vm_def.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7434,12 +7434,19 @@ ZEND_VM_HANDLER(203, ZEND_SILENCE_CATCH, ANY, ANY)
74347434
/* Set value to NULL */
74357435
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
74367436
/* Make internal functions which set a return value early return false */
7437+
/*
74377438
if (UNEXPECTED(Z_TYPE_P(EX_VAR(opline->result.var)) != IS_UNDEF
74387439
&& Z_TYPE_P(EX_VAR(opline->result.var)) <= IS_TRUE)) {
74397440
ZVAL_FALSE(EX_VAR(opline->result.var));
74407441
} else {
74417442
ZVAL_NULL(EX_VAR(opline->result.var));
74427443
}
7444+
*/
7445+
7446+
/* Set return value to null, except when an internal function has set a return value */
7447+
if (EXPECTED(Z_TYPE_P(EX_VAR(opline->result.var)) == IS_UNDEF)) {
7448+
ZVAL_NULL(EX_VAR(opline->result.var));
7449+
}
74437450
}
74447451
}
74457452

Zend/zend_vm_execute.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2937,12 +2937,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SILENCE_CATCH_SPEC_HANDLER(ZEN
29372937
/* Set value to NULL */
29382938
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
29392939
/* Make internal functions which set a return value early return false */
2940+
/*
29402941
if (UNEXPECTED(Z_TYPE_P(EX_VAR(opline->result.var)) != IS_UNDEF
29412942
&& Z_TYPE_P(EX_VAR(opline->result.var)) <= IS_TRUE)) {
29422943
ZVAL_FALSE(EX_VAR(opline->result.var));
29432944
} else {
29442945
ZVAL_NULL(EX_VAR(opline->result.var));
29452946
}
2947+
*/
2948+
2949+
/* Set return value to null, except when an internal function has set a return value */
2950+
if (EXPECTED(Z_TYPE_P(EX_VAR(opline->result.var)) == IS_UNDEF)) {
2951+
ZVAL_NULL(EX_VAR(opline->result.var));
2952+
}
29462953
}
29472954
}
29482955

ext/zend_test/test.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "zend_attributes.h"
2828
#include "zend_enum.h"
2929
#include "Zend/Optimizer/zend_optimizer.h"
30+
#include "zend_exceptions.h"
3031
#include "test_arginfo.h"
3132

3233
ZEND_DECLARE_MODULE_GLOBALS(zend_test)
@@ -250,21 +251,21 @@ static ZEND_FUNCTION(zend_suppress_exception_internal_return_false)
250251
ZEND_PARSE_PARAMETERS_NONE();
251252

252253
RETVAL_FALSE;
253-
zend_throw_error(NULL, "Shouldn't be seen");
254+
zend_throw_exception(NULL, "Shouldn't be seen", 0);
254255
}
255256
static ZEND_FUNCTION(zend_suppress_exception_internal_return_true)
256257
{
257258
ZEND_PARSE_PARAMETERS_NONE();
258259

259260
RETVAL_TRUE;
260-
zend_throw_error(NULL, "Shouldn't be seen");
261+
zend_throw_exception(NULL, "Shouldn't be seen", 0);
261262
}
262263
static ZEND_FUNCTION(zend_suppress_exception_internal_return_int)
263264
{
264265
ZEND_PARSE_PARAMETERS_NONE();
265266

266267
RETVAL_LONG(20);
267-
zend_throw_error(NULL, "Shouldn't be seen");
268+
zend_throw_exception(NULL, "Shouldn't be seen", 0);
268269
}
269270

270271
static zend_object *zend_test_class_new(zend_class_entry *class_type)

ext/zend_test/tests/suppress_exception_internal_return_false.phpt

Lines changed: 3 additions & 3 deletions
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

Lines changed: 3 additions & 5 deletions
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

Lines changed: 3 additions & 5 deletions
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)