diff options
-rw-r--r-- | Zend/tests/bug67111.phpt | 20 | ||||
-rw-r--r-- | ext/opcache/Optimizer/pass2.c | 12 |
2 files changed, 25 insertions, 7 deletions
diff --git a/Zend/tests/bug67111.phpt b/Zend/tests/bug67111.phpt new file mode 100644 index 0000000000..0fdfdfb517 --- /dev/null +++ b/Zend/tests/bug67111.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #67111: Memory leak when using "continue 2" inside two foreach loops +--FILE-- +<?php + +$array1 = [1, 2, 3]; +$array2 = [1, 2, 3]; + +foreach ($array1 as $x) { + foreach ($array2 as $y) { + echo "$x.$y\n"; + continue 2; + } +} + +?> +--EXPECT-- +1.1 +2.1 +3.1 diff --git a/ext/opcache/Optimizer/pass2.c b/ext/opcache/Optimizer/pass2.c index 4c839edf5a..b1c677237d 100644 --- a/ext/opcache/Optimizer/pass2.c +++ b/ext/opcache/Optimizer/pass2.c @@ -189,11 +189,10 @@ void zend_optimizer_pass2(zend_op_array *op_array) int nest_levels; int dont_optimize = 0; - if (ZEND_OP2_TYPE(opline) != IS_CONST) { - break; - } - convert_to_long(&ZEND_OP2_LITERAL(opline)); - nest_levels = ZEND_OP2_LITERAL(opline).value.lval; + ZEND_ASSERT(ZEND_OP2_TYPE(opline) == IS_CONST); + ZEND_ASSERT(Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_LONG); + + nest_levels = Z_LVAL(ZEND_OP2_LITERAL(opline)); array_offset = ZEND_OP1(opline).opline_num; while (1) { @@ -204,8 +203,7 @@ void zend_optimizer_pass2(zend_op_array *op_array) jmp_to = &op_array->brk_cont_array[array_offset]; array_offset = jmp_to->parent; if (--nest_levels > 0) { - if (opline->opcode == ZEND_BRK && - op_array->opcodes[jmp_to->brk].opcode == ZEND_FREE) { + if (op_array->opcodes[jmp_to->brk].opcode == ZEND_FREE) { dont_optimize = 1; break; } |