Browse Source

Fixed incorrect order of free/finally on exception

pull/1637/head
Dmitry Stogov 10 years ago
parent
commit
d66d1b97aa
  1. 2
      Zend/tests/try/try_finally_020.phpt
  2. 11
      Zend/zend_execute.c
  3. 19
      Zend/zend_vm_def.h
  4. 19
      Zend/zend_vm_execute.h

2
Zend/tests/try/try_finally_020.phpt

@ -1,7 +1,5 @@
--TEST--
Combination of foreach, finally and exception (call order)
--XFAIL--
See Bug #62210 and attempt to fix it in "tmp_liveliness" branch
--FILE--
<?php
class A {

11
Zend/zend_execute.c

@ -2418,7 +2418,7 @@ static zend_always_inline zend_generator *zend_get_running_generator(zend_execut
}
/* }}} */
static zend_always_inline void i_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) /* {{{ */
static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t op_num) /* {{{ */
{
int i;
if (UNEXPECTED(EX(call))) {
@ -2543,6 +2543,12 @@ static zend_always_inline void i_cleanup_unfinished_execution(zend_execute_data
call = EX(call);
} while (call);
}
}
/* }}} */
static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) /* {{{ */
{
int i;
for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
const zend_brk_cont_element *brk_cont = &EX(func)->op_array.brk_cont_array[i];
@ -2592,7 +2598,8 @@ static zend_always_inline void i_cleanup_unfinished_execution(zend_execute_data
/* }}} */
void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) {
i_cleanup_unfinished_execution(execute_data, op_num, catch_op_num);
cleanup_unfinished_calls(execute_data, op_num);
cleanup_live_vars(execute_data, op_num, catch_op_num);
}
#ifdef HAVE_GCC_GLOBAL_REGS

19
Zend/zend_vm_def.h

@ -7124,11 +7124,12 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
}
}
i_cleanup_unfinished_execution(execute_data, op_num, catch_op_num);
cleanup_unfinished_calls(execute_data, op_num);
if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) {
zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
cleanup_live_vars(execute_data, op_num, finally_op_num);
if (in_finally && Z_OBJ_P(fast_call)) {
zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call));
}
@ -7138,6 +7139,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op_num]);
ZEND_VM_CONTINUE();
} else {
cleanup_live_vars(execute_data, op_num, catch_op_num);
if (in_finally) {
/* we are going out of current finally scope */
zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
@ -7557,20 +7559,25 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY)
USE_OPLINE
if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) {
cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, opline->op2.opline_num);
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else {
EG(exception) = Z_OBJ_P(fast_call);
Z_OBJ_P(fast_call) = NULL;
if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, opline->op2.opline_num);
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
zend_generator *generator = zend_get_running_generator(execute_data);
zend_generator_close(generator, 1);
ZEND_VM_RETURN();
} else {
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, 0);
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
zend_generator *generator = zend_get_running_generator(execute_data);
zend_generator_close(generator, 1);
ZEND_VM_RETURN();
} else {
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
}
}
}

19
Zend/zend_vm_execute.h

@ -1514,11 +1514,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(
}
}
i_cleanup_unfinished_execution(execute_data, op_num, catch_op_num);
cleanup_unfinished_calls(execute_data, op_num);
if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) {
zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
cleanup_live_vars(execute_data, op_num, finally_op_num);
if (in_finally && Z_OBJ_P(fast_call)) {
zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call));
}
@ -1528,6 +1529,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op_num]);
ZEND_VM_CONTINUE();
} else {
cleanup_live_vars(execute_data, op_num, catch_op_num);
if (in_finally) {
/* we are going out of current finally scope */
zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
@ -1639,20 +1641,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPC
USE_OPLINE
if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) {
cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, opline->op2.opline_num);
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else {
EG(exception) = Z_OBJ_P(fast_call);
Z_OBJ_P(fast_call) = NULL;
if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, opline->op2.opline_num);
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
zend_generator *generator = zend_get_running_generator(execute_data);
zend_generator_close(generator, 1);
ZEND_VM_RETURN();
} else {
ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, 0);
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
zend_generator *generator = zend_get_running_generator(execute_data);
zend_generator_close(generator, 1);
ZEND_VM_RETURN();
} else {
ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));
}
}
}
}

Loading…
Cancel
Save