--- /dev/null
+--TEST--
+Break out of while loop that is followed by a return statement and inside a foreach loop
+--FILE--
+<?php
+
+$a = [42];
+foreach ($a as $b) {
+ while (1) {
+ break 2;
+ }
+ return;
+}
+?>
+===DONE===
+--EXPECT--
+===DONE===
static void zend_free_foreach_and_switch_variables(void) /* {{{ */
{
- uint32_t opnum_start, opnum_end, i;
-
- opnum_start = get_next_op_number(CG(active_op_array));
-
zend_stack_apply(&CG(loop_var_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_loop_var);
-
- opnum_end = get_next_op_number(CG(active_op_array));
-
- for (i = opnum_start; i < opnum_end; ++i) {
- CG(active_op_array)->opcodes[i].extended_value |= EXT_TYPE_FREE_ON_RETURN;
- }
}
/* }}} */
#define ZEND_FETCH_ARG_MASK 0x000fffff
-#define EXT_TYPE_FREE_ON_RETURN (1<<2)
-
#define ZEND_MEMBER_FUNC_CALL 1<<0
#define ZEND_ARG_SEND_BY_REF (1<<0)
do {
ZEND_ASSERT(array_offset != -1);
jmp_to = &op_array->brk_cont_array[array_offset];
- if (nest_levels>1) {
+ if (nest_levels > 1 && jmp_to->start >= 0) {
zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
if (brk_opline->opcode == ZEND_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
- }
+ zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
} else if (brk_opline->opcode == ZEND_FE_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval *var = EX_VAR(brk_opline->op1.var);
- if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
- zend_hash_iterator_del(Z_FE_ITER_P(var));
- }
- zval_ptr_dtor_nogc(var);
+ zval *var = EX_VAR(brk_opline->op1.var);
+ if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
+ zend_hash_iterator_del(Z_FE_ITER_P(var));
}
+ zval_ptr_dtor_nogc(var);
}
}
array_offset = jmp_to->parent;
ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
{
- zend_op *brk_opline;
USE_OPLINE
zend_brk_cont_element *el;
el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->extended_value,
&EX(func)->op_array, execute_data);
- brk_opline = EX(func)->op_array.opcodes + el->brk;
+ if (el->start >= 0) {
+ zend_op *brk_opline = EX(func)->op_array.opcodes + el->brk;
- if (brk_opline->opcode == ZEND_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ if (brk_opline->opcode == ZEND_FREE) {
zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
- }
- } else if (brk_opline->opcode == ZEND_FE_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ } else if (brk_opline->opcode == ZEND_FE_FREE) {
zval *var = EX_VAR(brk_opline->op1.var);
if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
zend_hash_iterator_del(Z_FE_ITER_P(var));
zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
if (brk_opline->opcode == ZEND_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
- }
+ zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
} else if (brk_opline->opcode == ZEND_FE_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval *var = EX_VAR(brk_opline->op1.var);
- if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
- zend_hash_iterator_del(Z_FE_ITER_P(var));
- }
- zval_ptr_dtor_nogc(var);
+ zval *var = EX_VAR(brk_opline->op1.var);
+ if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
+ zend_hash_iterator_del(Z_FE_ITER_P(var));
}
+ zval_ptr_dtor_nogc(var);
} else if (brk_opline->opcode == ZEND_END_SILENCE) {
/* restore previous error_reporting value */
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
if (brk_opline->opcode == ZEND_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
- }
+ zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
} else if (brk_opline->opcode == ZEND_FE_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval *var = EX_VAR(brk_opline->op1.var);
- if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
- zend_hash_iterator_del(Z_FE_ITER_P(var));
- }
- zval_ptr_dtor_nogc(var);
+ zval *var = EX_VAR(brk_opline->op1.var);
+ if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
+ zend_hash_iterator_del(Z_FE_ITER_P(var));
}
+ zval_ptr_dtor_nogc(var);
} else if (brk_opline->opcode == ZEND_END_SILENCE) {
/* restore previous error_reporting value */
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *brk_opline;
USE_OPLINE
zend_brk_cont_element *el;
el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->extended_value,
&EX(func)->op_array, execute_data);
- brk_opline = EX(func)->op_array.opcodes + el->brk;
+ if (el->start >= 0) {
+ zend_op *brk_opline = EX(func)->op_array.opcodes + el->brk;
- if (brk_opline->opcode == ZEND_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ if (brk_opline->opcode == ZEND_FREE) {
zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
- }
- } else if (brk_opline->opcode == ZEND_FE_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ } else if (brk_opline->opcode == ZEND_FE_FREE) {
zval *var = EX_VAR(brk_opline->op1.var);
if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
zend_hash_iterator_del(Z_FE_ITER_P(var));