Skip to content

Commit 772ea8e

Browse files
committed
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: Fix block pass dropping ZEND_FAST_CALL OP2 definition
2 parents 62a2b3d + 139c84b commit 772ea8e

3 files changed

Lines changed: 58 additions & 0 deletions

File tree

‎NEWS‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ PHP NEWS
157157
. Fixed bug GH-23572 (Tracing JIT calls the wrong method for self::/parent::
158158
static calls in trait methods shared by several classes). (jorgsowa,
159159
mgoulart)
160+
. Fix block pass dropping ZEND_FAST_CALL OP2 definition. (Mrmaxmeier)
160161

161162
- OpenSSL:
162163
. Fixed bug GH-24784 (openssl_pkcs7_read() and openssl_cms_read() overwrite

‎Zend/Optimizer/block_pass.c‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,18 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
400400
}
401401
break;
402402

403+
case ZEND_FAST_CALL:
404+
if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
405+
/* OP2 holds the pending return value. A TMP normally has a single
406+
* consumer, but FAST_CALL reads does not consume it:
407+
* the RETURN behind it is the consumer, and
408+
* zend_dispatch_try_catch_finally_helper() destroys the value
409+
* through OP2 if the finally block throws. Propagating the source
410+
* into the RETURN therefore must not remove it. */
411+
Tsource[VAR_NUM(opline->op2.var)] = NULL;
412+
}
413+
break;
414+
403415
case ZEND_SWITCH_LONG:
404416
case ZEND_SWITCH_STRING:
405417
case ZEND_MATCH:
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
Block pass must not remove the source of the ZEND_FAST_CALL OP2 return value
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
--FILE--
9+
<?php
10+
function test_scalar() {
11+
$x = 1;
12+
try {
13+
try {
14+
return true ? 1.5 : 2.5;
15+
} finally {
16+
undef_fn();
17+
}
18+
} catch (Throwable $e) {
19+
echo $e::class, ': ', $e->getMessage(), "\n";
20+
}
21+
return "fallback";
22+
}
23+
24+
function test_refcounted() {
25+
$x = 1;
26+
try {
27+
try {
28+
return true ? "returned" : "other";
29+
} finally {
30+
undef_fn();
31+
}
32+
} catch (Throwable $e) {
33+
echo $e::class, ': ', $e->getMessage(), "\n";
34+
}
35+
return "fallback";
36+
}
37+
38+
var_dump(test_scalar());
39+
var_dump(test_refcounted());
40+
?>
41+
--EXPECT--
42+
Error: Call to undefined function undef_fn()
43+
string(8) "fallback"
44+
Error: Call to undefined function undef_fn()
45+
string(8) "fallback"

0 commit comments

Comments
 (0)