From af1a7b7b72de7db01f32e84bdc7ced904cd68b81 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 1 Aug 2022 14:00:19 +0300 Subject: [PATCH] Fix SSA reconstruction when body of "foreach" loop is removed Fixes oss-fuzz #49483 --- ext/opcache/Optimizer/dfa_pass.c | 19 +++++++++++++++++++ ext/opcache/tests/opt/fe_fetch_001.phpt | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 ext/opcache/tests/opt/fe_fetch_001.phpt diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index 496ff5618e1..49f27b1151d 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -699,13 +699,32 @@ static void zend_ssa_unlink_block(zend_op_array *op_array, zend_ssa *ssa, zend_b { if (block->predecessors_count == 1 && ssa->blocks[block_num].phis == NULL) { int *predecessors, i; + zend_basic_block *fe_fetch_block = NULL; ZEND_ASSERT(block->successors_count == 1); predecessors = &ssa->cfg.predecessors[block->predecessor_offset]; + if (block->predecessors_count == 1 && (block->flags & ZEND_BB_FOLLOW)) { + zend_basic_block *pred_block = &ssa->cfg.blocks[predecessors[0]]; + + if (pred_block->len > 0 && (pred_block->flags & ZEND_BB_REACHABLE)) { + if ((op_array->opcodes[pred_block->start + pred_block->len - 1].opcode == ZEND_FE_FETCH_R + || op_array->opcodes[pred_block->start + pred_block->len - 1].opcode == ZEND_FE_FETCH_RW) + && op_array->opcodes[pred_block->start + pred_block->len - 1].op2_type == IS_CV) { + fe_fetch_block = pred_block; + } + } + } for (i = 0; i < block->predecessors_count; i++) { zend_ssa_replace_control_link(op_array, ssa, predecessors[i], block_num, block->successors[0]); } zend_ssa_remove_block(op_array, ssa, block_num); + if (fe_fetch_block && fe_fetch_block->successors[0] == fe_fetch_block->successors[1]) { + /* The body of "foreach" loop was removed */ + int ssa_var = ssa->ops[fe_fetch_block->start + fe_fetch_block->len - 1].op2_def; + if (ssa_var >= 0) { + zend_ssa_remove_uses_of_var(ssa, ssa_var); + } + } } } diff --git a/ext/opcache/tests/opt/fe_fetch_001.phpt b/ext/opcache/tests/opt/fe_fetch_001.phpt new file mode 100644 index 00000000000..b1f7d86ddcc --- /dev/null +++ b/ext/opcache/tests/opt/fe_fetch_001.phpt @@ -0,0 +1,21 @@ +--TEST-- +FE_FETCH 001: SSA reconstruction when body of "foreach" loop is removed +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECT-- +DONE