Skip to content

Commit af1a7b7

Browse files
committed
Fix SSA reconstruction when body of "foreach" loop is removed
Fixes oss-fuzz #49483
1 parent 4147257 commit af1a7b7

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

ext/opcache/Optimizer/dfa_pass.c

+19
Original file line numberDiff line numberDiff line change
@@ -699,13 +699,32 @@ static void zend_ssa_unlink_block(zend_op_array *op_array, zend_ssa *ssa, zend_b
699699
{
700700
if (block->predecessors_count == 1 && ssa->blocks[block_num].phis == NULL) {
701701
int *predecessors, i;
702+
zend_basic_block *fe_fetch_block = NULL;
702703

703704
ZEND_ASSERT(block->successors_count == 1);
704705
predecessors = &ssa->cfg.predecessors[block->predecessor_offset];
706+
if (block->predecessors_count == 1 && (block->flags & ZEND_BB_FOLLOW)) {
707+
zend_basic_block *pred_block = &ssa->cfg.blocks[predecessors[0]];
708+
709+
if (pred_block->len > 0 && (pred_block->flags & ZEND_BB_REACHABLE)) {
710+
if ((op_array->opcodes[pred_block->start + pred_block->len - 1].opcode == ZEND_FE_FETCH_R
711+
|| op_array->opcodes[pred_block->start + pred_block->len - 1].opcode == ZEND_FE_FETCH_RW)
712+
&& op_array->opcodes[pred_block->start + pred_block->len - 1].op2_type == IS_CV) {
713+
fe_fetch_block = pred_block;
714+
}
715+
}
716+
}
705717
for (i = 0; i < block->predecessors_count; i++) {
706718
zend_ssa_replace_control_link(op_array, ssa, predecessors[i], block_num, block->successors[0]);
707719
}
708720
zend_ssa_remove_block(op_array, ssa, block_num);
721+
if (fe_fetch_block && fe_fetch_block->successors[0] == fe_fetch_block->successors[1]) {
722+
/* The body of "foreach" loop was removed */
723+
int ssa_var = ssa->ops[fe_fetch_block->start + fe_fetch_block->len - 1].op2_def;
724+
if (ssa_var >= 0) {
725+
zend_ssa_remove_uses_of_var(ssa, ssa_var);
726+
}
727+
}
709728
}
710729
}
711730

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
FE_FETCH 001: SSA reconstruction when body of "foreach" loop is removed
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
--FILE--
8+
<?php
9+
function test() {
10+
$j = 0;
11+
for ($i = 0; $i < 77; $i++) {
12+
for ($i = 5; $i <= 1; $i++)
13+
$obj = (object)$arr;
14+
foreach ($obj as $val)
15+
if ($j < 14) break;
16+
}
17+
}
18+
?>
19+
DONE
20+
--EXPECT--
21+
DONE

0 commit comments

Comments
 (0)