Browse Source

Fixed invalid live-range detection

pull/1402/head
Dmitry Stogov 10 years ago
parent
commit
54f367ee2a
  1. 22
      Zend/tests/temporary_cleaning_007.phpt
  2. 23
      Zend/zend_compile.c
  3. 4
      Zend/zend_compile.h
  4. 8
      Zend/zend_opcode.c

22
Zend/tests/temporary_cleaning_007.phpt

@ -0,0 +1,22 @@
--TEST--
Exception inside a foreach loop with return
--FILE--
<?php
class saboteurTestController {
public function isConsistent() { throw new \Exception(); }
}
$controllers = array(new saboteurTestController(),new saboteurTestController());
foreach ($controllers as $controller) {
try {
if ($controller->isConsistent()) {
return $controller;
}
} catch (\Exception $e) {
echo "Exception\n";
}
}
?>
--EXPECT--
Exception
Exception

23
Zend/zend_compile.c

@ -872,7 +872,7 @@ static void str_dtor(zval *zv) /* {{{ */ {
static zend_bool zend_is_call(zend_ast *ast);
static void generate_free_loop_var(znode *var) /* {{{ */
static void generate_free_loop_var_ex(znode *var, uint32_t flags) /* {{{ */
{
if (var->op_type != IS_UNUSED) {
zend_op *opline = get_next_op(CG(active_op_array));
@ -880,10 +880,16 @@ static void generate_free_loop_var(znode *var) /* {{{ */
opline->opcode = var->flag ? ZEND_FE_FREE : ZEND_FREE;
SET_NODE(opline->op1, var);
SET_UNUSED(opline->op2);
opline->extended_value = flags;
}
}
/* }}} */
static void generate_free_loop_var(znode *var) /* {{{ */
{
generate_free_loop_var_ex(var, 0);
}
static uint32_t zend_add_try_element(uint32_t try_op) /* {{{ */
{
zend_op_array *op_array = CG(active_op_array);
@ -3442,12 +3448,12 @@ void zend_compile_unset(zend_ast *ast) /* {{{ */
}
/* }}} */
static void zend_free_foreach_and_switch_variables(void) /* {{{ */
static void zend_free_foreach_and_switch_variables(uint32_t flags) /* {{{ */
{
int array_offset = CG(context).current_brk_cont;
while (array_offset != -1) {
zend_brk_cont_element *brk_cont = &CG(context).brk_cont_array[array_offset];
generate_free_loop_var(&brk_cont->loop_var);
generate_free_loop_var_ex(&brk_cont->loop_var, flags);
array_offset = brk_cont->parent;
}
}
@ -3471,7 +3477,12 @@ void zend_compile_return(zend_ast *ast) /* {{{ */
zend_compile_expr(&expr_node, expr_ast);
}
zend_free_foreach_and_switch_variables();
/* Generator return types are handled separately */
if (!(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) && CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
zend_emit_return_type_check(expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1);
}
zend_free_foreach_and_switch_variables(ZEND_FREE_ON_RETURN);
if (CG(context).in_finally) {
opline = zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL);
@ -3479,10 +3490,6 @@ void zend_compile_return(zend_ast *ast) /* {{{ */
opline->op1.var = CG(context).fast_call_var;
}
/* Generator return types are handled separately */
if (!(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) && CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
zend_emit_return_type_check(expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1);
}
opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN,
&expr_node, NULL);

4
Zend/zend_compile.h

@ -882,7 +882,9 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name);
#define ZEND_FETCH_ARG_MASK 0x000fffff
#define ZEND_MEMBER_FUNC_CALL 1<<0
#define ZEND_FREE_ON_RETURN (1<<0)
#define ZEND_MEMBER_FUNC_CALL (1<<0)
#define ZEND_ARG_SEND_BY_REF (1<<0)
#define ZEND_ARG_COMPILE_TIME_BOUND (1<<1)

8
Zend/zend_opcode.c

@ -991,7 +991,11 @@ static zend_always_inline uint32_t *generate_var_liveliness_info_ex(zend_op_arra
&& opline->opcode != ZEND_FETCH_LIST
&& opline->opcode != ZEND_CASE
&& opline->opcode != ZEND_FE_FETCH_R
&& opline->opcode != ZEND_FE_FETCH_RW) {
&& opline->opcode != ZEND_FE_FETCH_RW
/* the following opcodes are not the "final" */
&& (opline->opcode != ZEND_FREE || !(opline->extended_value & ZEND_FREE_ON_RETURN))
&& (opline->opcode != ZEND_FE_FREE || !(opline->extended_value & ZEND_FREE_ON_RETURN))
) {
op_live_total += liveliness_kill_var(op_array, opline, var, Tstart, opTs);
}
}
@ -1007,7 +1011,7 @@ static zend_always_inline uint32_t *generate_var_liveliness_info_ex(zend_op_arra
}
} while (++opline != end);
#if ZEND_DEBUG
#if 0
/* Check that all TMP variable live-ranges are closed */
for (i = 0; i < op_array->T; i++) {
ZEND_ASSERT(Tstart[i] == (uint32_t)-1);

Loading…
Cancel
Save