Skip to content

Commit 0ac3d78

Browse files
committed
Fix incorrect JMP optimization
Fixes oss-fuzz #42155
1 parent efb901e commit 0ac3d78

File tree

2 files changed

+21
-4
lines changed

2 files changed

+21
-4
lines changed

ext/opcache/Optimizer/dfa_pass.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -730,9 +730,13 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
730730
uint32_t op_num;
731731
zend_op *opline;
732732
zend_ssa_op *ssa_op;
733+
zend_bool can_follow = 1;
733734

734735
while (next_block_num < ssa->cfg.blocks_count
735736
&& !(ssa->cfg.blocks[next_block_num].flags & ZEND_BB_REACHABLE)) {
737+
if (ssa->cfg.blocks[next_block_num].flags & ZEND_BB_UNREACHABLE_FREE) {
738+
can_follow = 0;
739+
}
736740
next_block_num++;
737741
}
738742

@@ -744,7 +748,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
744748
switch (opline->opcode) {
745749
case ZEND_JMP:
746750
optimize_jmp:
747-
if (block->successors[0] == next_block_num) {
751+
if (block->successors[0] == next_block_num && can_follow) {
748752
MAKE_NOP(opline);
749753
removed_ops++;
750754
goto optimize_nop;
@@ -765,7 +769,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
765769
goto optimize_jmp;
766770
}
767771
} else {
768-
if (block->successors[0] == next_block_num) {
772+
if (block->successors[0] == next_block_num && can_follow) {
769773
take_successor_0(ssa, block_num, block);
770774
if (opline->op1_type == IS_CV && (OP1_INFO() & MAY_BE_UNDEF)) {
771775
opline->opcode = ZEND_CHECK_VAR;
@@ -796,7 +800,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
796800
goto optimize_nop;
797801
}
798802
} else if (block->successors_count == 2) {
799-
if (block->successors[0] == next_block_num) {
803+
if (block->successors[0] == next_block_num && can_follow) {
800804
take_successor_0(ssa, block_num, block);
801805
if (opline->op1_type == IS_CV && (OP1_INFO() & MAY_BE_UNDEF)) {
802806
opline->opcode = ZEND_CHECK_VAR;
@@ -830,7 +834,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
830834
} else if (block->successors_count == 2) {
831835
if (block->successors[0] == block->successors[1]) {
832836
take_successor_0(ssa, block_num, block);
833-
if (block->successors[0] == next_block_num) {
837+
if (block->successors[0] == next_block_num && can_follow) {
834838
if (opline->op1_type == IS_CV && (OP1_INFO() & MAY_BE_UNDEF)) {
835839
opline->opcode = ZEND_CHECK_VAR;
836840
opline->op2.num = 0;

ext/opcache/tests/opt/jmp_002.phpt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
JMP 002: JMP around unreachable FREE
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
--FILE--
8+
<?php
9+
7??match(X){};
10+
?>
11+
DONE
12+
--EXPECT--
13+
DONE

0 commit comments

Comments
 (0)