diff --git a/Zend/Optimizer/zend_cfg.c b/Zend/Optimizer/zend_cfg.c index 05cb36dd34428..de54844b35c96 100644 --- a/Zend/Optimizer/zend_cfg.c +++ b/Zend/Optimizer/zend_cfg.c @@ -370,9 +370,14 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: + case ZEND_JMP_NULL: + BB_START(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes); + if (i + 1 < op_array->last) { + BB_START(i + 1); + } + break; case ZEND_COALESCE: case ZEND_ASSERT_CHECK: - case ZEND_JMP_NULL: case ZEND_BIND_INIT_STATIC_OR_JMP: BB_START(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes); BB_START(i + 1); @@ -524,9 +529,17 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: + case ZEND_JMP_NULL: + block->successors_count = 2; + block->successors[0] = block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes]; + if (j + 1 < blocks_count) { + block->successors[1] = j + 1; + } else { + block->successors[1] = j; /* last instruction and its own target */ + } + break; case ZEND_COALESCE: case ZEND_ASSERT_CHECK: - case ZEND_JMP_NULL: case ZEND_BIND_INIT_STATIC_OR_JMP: block->successors_count = 2; block->successors[0] = block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes]; diff --git a/ext/opcache/tests/opt/gh20733.phpt b/ext/opcache/tests/opt/gh20733.phpt new file mode 100644 index 0000000000000..60e013d161d55 --- /dev/null +++ b/ext/opcache/tests/opt/gh20733.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-20733 (heap buffer overflow in optimizer) +--INI-- +opcache.jit=tracing +opcache.jit_buffer_size=16M +--EXTENSIONS-- +opcache +--FILE-- + 'php://temp','line-length' => $undef]; + $arr2 = []; + $and = $arr1 and $arr2; + + while ($and) { + } +} +echo "Done"; +?> +--EXPECT-- +Done