Skip to content

Commit 038bc27

Browse files
committed
Handle pi nodes in replace_predecessor
If we're removing a predecessor because it already exists during replacement, we should also drop pi nodes for that predecessor. Fixes oss-fuzz #39276.
1 parent 3adbafe commit 038bc27

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

Zend/tests/replace_pred_pi_node.phpt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
Handling of pi nodes when replacing a predecessor
3+
--FILE--
4+
<?php
5+
function test(bool $a, bool $b) {
6+
$byte = '';
7+
if ($a && $byte > 0 && $b) {}
8+
unknown($byte);
9+
}
10+
?>
11+
===DONE===
12+
--EXPECT--
13+
===DONE===

ext/opcache/Optimizer/dfa_pass.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -575,11 +575,19 @@ static void replace_predecessor(zend_ssa *ssa, int block_id, int old_pred, int n
575575

576576
/* Also remove the corresponding phi node entries */
577577
for (phi = ssa->blocks[block_id].phis; phi; phi = phi->next) {
578-
memmove(
579-
phi->sources + old_pred_idx,
580-
phi->sources + old_pred_idx + 1,
581-
sizeof(int) * (block->predecessors_count - old_pred_idx - 1)
582-
);
578+
if (phi->pi >= 0) {
579+
if (phi->pi == old_pred) {
580+
zend_ssa_rename_var_uses(
581+
ssa, phi->ssa_var, phi->sources[0], /* update_types */ 0);
582+
zend_ssa_remove_phi(ssa, phi);
583+
}
584+
} else {
585+
memmove(
586+
phi->sources + old_pred_idx,
587+
phi->sources + old_pred_idx + 1,
588+
sizeof(int) * (block->predecessors_count - old_pred_idx - 1)
589+
);
590+
}
583591
}
584592

585593
block->predecessors_count--;

0 commit comments

Comments
 (0)