Skip to content

Commit c4b2a40

Browse files
committed
Merge branch 'PHP-8.0'
* PHP-8.0: Fix incorrectly optimized out live range
2 parents e974bec + 9cfb526 commit c4b2a40

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

Zend/tests/live_range_phi_leak.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Missing live range if part of phi
3+
--FILE--
4+
<?php
5+
function doThrow() {
6+
throw new Exception("Test");
7+
}
8+
function test($k) {
9+
// The 0 gives the QM_ASSIGN a non-refcounted type.
10+
$res[$k ? $k : 0] = doThrow();
11+
}
12+
try {
13+
test(new stdClass);
14+
} catch (Exception $e) {
15+
echo $e->getMessage(), "\n";
16+
}
17+
?>
18+
--EXPECT--
19+
Test

ext/opcache/Optimizer/zend_optimizer.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,11 +1350,21 @@ static void zend_adjust_fcall_stack_size_graph(zend_op_array *op_array)
13501350
static zend_bool needs_live_range(zend_op_array *op_array, zend_op *def_opline) {
13511351
zend_func_info *func_info = ZEND_FUNC_INFO(op_array);
13521352
zend_ssa_op *ssa_op = &func_info->ssa.ops[def_opline - op_array->opcodes];
1353-
if (ssa_op->result_def >= 0) {
1354-
uint32_t type = func_info->ssa.var_info[ssa_op->result_def].type;
1355-
return (type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) != 0;
1353+
int ssa_var = ssa_op->result_def;
1354+
if (ssa_var < 0) {
1355+
/* Be conservative. */
1356+
return 1;
13561357
}
1357-
return 1;
1358+
1359+
/* If the variable is used by a PHI, this may be the assignment of the final branch of a
1360+
* ternary/etc structure. While this is where the live range starts, the value from the other
1361+
* branch may also be used. As such, use the type of the PHI node for the following check. */
1362+
if (func_info->ssa.vars[ssa_var].phi_use_chain) {
1363+
ssa_var = func_info->ssa.vars[ssa_var].phi_use_chain->ssa_var;
1364+
}
1365+
1366+
uint32_t type = func_info->ssa.var_info[ssa_var].type;
1367+
return (type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) != 0;
13581368
}
13591369

13601370
void zend_foreach_op_array(zend_script *script, zend_op_array_func_t func, void *context)

0 commit comments

Comments
 (0)