summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/bug67111.phpt20
-rw-r--r--ext/opcache/Optimizer/pass2.c12
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;
}