diff options
| author | Dmitry Stogov <dmitry@zend.com> | 2016-06-08 02:20:45 +0300 |
|---|---|---|
| committer | Dmitry Stogov <dmitry@zend.com> | 2016-06-08 02:20:45 +0300 |
| commit | 10f056255efc741654393c21b234d29333489354 (patch) | |
| tree | e19095ac043846e368f69b667bc263f88deddb2a /Zend/zend_compile.c | |
| parent | 2bae4e18a2a0041bdbf0511cb4fed73c595f4050 (diff) | |
| download | php-git-10f056255efc741654393c21b234d29333489354.tar.gz | |
Better fix for bug #70228 (memleak if return in finally block)
Diffstat (limited to 'Zend/zend_compile.c')
| -rw-r--r-- | Zend/zend_compile.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index ce8224652d..30d28cd842 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4000,7 +4000,7 @@ void zend_compile_unset(zend_ast *ast) /* {{{ */ } /* }}} */ -static int zend_handle_loops_and_finally_ex(zend_long depth) /* {{{ */ +static int zend_handle_loops_and_finally_ex(zend_long depth, znode *return_value) /* {{{ */ { zend_loop_var *base; zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack)); @@ -4017,7 +4017,11 @@ static int zend_handle_loops_and_finally_ex(zend_long depth) /* {{{ */ opline->result_type = IS_TMP_VAR; opline->result.var = loop_var->var_num; SET_UNUSED(opline->op1); - SET_UNUSED(opline->op2); + if (return_value) { + SET_NODE(opline->op2, return_value); + } else { + SET_UNUSED(opline->op2); + } opline->op1.num = loop_var->u.try_catch_offset; } else if (loop_var->opcode == ZEND_DISCARD_EXCEPTION) { zend_op *opline = get_next_op(CG(active_op_array)); @@ -4051,9 +4055,9 @@ static int zend_handle_loops_and_finally_ex(zend_long depth) /* {{{ */ } /* }}} */ -static int zend_handle_loops_and_finally(void) /* {{{ */ +static int zend_handle_loops_and_finally(znode *return_value) /* {{{ */ { - return zend_handle_loops_and_finally_ex(zend_stack_count(&CG(loop_var_stack)) + 1); + return zend_handle_loops_and_finally_ex(zend_stack_count(&CG(loop_var_stack)) + 1, return_value); } /* }}} */ @@ -4080,7 +4084,7 @@ void zend_compile_return(zend_ast *ast) /* {{{ */ expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, 0); } - zend_handle_loops_and_finally(); + zend_handle_loops_and_finally((expr_node.op_type & (IS_TMP_VAR | IS_VAR)) ? &expr_node : NULL); opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN, &expr_node, NULL); @@ -4150,7 +4154,7 @@ void zend_compile_break_continue(zend_ast *ast) /* {{{ */ zend_error_noreturn(E_COMPILE_ERROR, "'%s' not in the 'loop' or 'switch' context", ast->kind == ZEND_AST_BREAK ? "break" : "continue"); } else { - if (!zend_handle_loops_and_finally_ex(depth)) { + if (!zend_handle_loops_and_finally_ex(depth, NULL)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot '%s' %d level%s", ast->kind == ZEND_AST_BREAK ? "break" : "continue", depth, depth == 1 ? "" : "s"); @@ -4233,7 +4237,7 @@ void zend_compile_goto(zend_ast *ast) /* {{{ */ zend_compile_expr(&label_node, label_ast); /* Label resolution and unwinding adjustments happen in pass two. */ - zend_handle_loops_and_finally(); + zend_handle_loops_and_finally(NULL); opline = zend_emit_op(NULL, ZEND_GOTO, NULL, &label_node); opline->op1.num = get_next_op_number(CG(active_op_array)) - opnum_start - 1; opline->extended_value = CG(context).current_brk_cont; |
