diff options
| author | Dmitry Stogov <dmitry@zend.com> | 2016-05-25 01:25:12 +0300 |
|---|---|---|
| committer | Dmitry Stogov <dmitry@zend.com> | 2016-05-25 01:25:12 +0300 |
| commit | 2ae21abdf7b87ee95d76aca22e787408d7c766cf (patch) | |
| tree | 26c8c6ba8f81f077c10cd5031b3d8b79ecdaa064 /Zend/zend_compile.c | |
| parent | 91f5940329fede8a26b64e99d4d6d858fe8654cc (diff) | |
| download | php-git-2ae21abdf7b87ee95d76aca22e787408d7c766cf.tar.gz | |
Fixed bug #72213 (Finally leaks on nested exceptions).
Squashed commit of the following:
commit 8461b0407fc9eab0869d43b84e6a92ba2fe06997
Author: Dmitry Stogov <dmitry@zend.com>
Date: Wed May 25 00:34:42 2016 +0300
Rmoved zend_try_catch_element.parent and walk through op_array.try_catch_array backward from the current try_cacth_offset.
commit 0c71e249649bed178bfbef30bb3e63c57f07af05
Author: Dmitry Stogov <dmitry@zend.com>
Date: Wed May 25 00:04:53 2016 +0300
Move SAVE_OPLINE() to its original place
commit 111432a4df738fcd65878a42f23194dc3c4983a2
Author: Dmitry Stogov <dmitry@zend.com>
Date: Wed May 25 00:01:10 2016 +0300
Separate the common part of ZEND_HANDLE_EXCEPTION and FAST_RET into zend_dispatch_try_catch_finally_helper.
commit 4f21c06c2ec17819a708bc037f318784554a6ecd
Author: Nikita Popov <nikic@php.net>
Date: Tue May 24 14:55:27 2016 +0200
Improve finally fix
commit da5c7274997b8308e682b5bf280124e3a1483086
Author: Dmitry Stogov <dmitry@zend.com>
Date: Tue May 24 10:36:08 2016 +0300
Fixed Zend/tests/try/bug70228_3.phpt and Zend/tests/try/bug70228_4.phpt
commit cfcedf2fb4f4fc1f7de9f7d53a3037fed7795f19
Author: Dmitry Stogov <dmitry@zend.com>
Date: Tue May 24 02:59:27 2016 +0300
Added test
commit 4c6aa93d43da941eb4fda15b48154bfb104bdc04
Author: Dmitry Stogov <dmitry@zend.com>
Date: Tue May 24 00:38:20 2016 +0300
Added tests
commit 8a8f4704b0eca2e460d42c1f253a363b0db8e510
Author: Dmitry Stogov <dmitry@zend.com>
Date: Mon May 23 23:27:34 2016 +0300
Fixed bug #72213 (Finally leaks on nested exceptions)
Diffstat (limited to 'Zend/zend_compile.c')
| -rw-r--r-- | Zend/zend_compile.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 0994681c20..c6da34732a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -234,6 +234,7 @@ void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */ CG(context).backpatch_count = 0; CG(context).in_finally = 0; CG(context).fast_call_var = -1; + CG(context).try_catch_offset = -1; CG(context).current_brk_cont = -1; CG(context).last_brk_cont = 0; CG(context).brk_cont_array = NULL; @@ -4008,6 +4009,12 @@ static int zend_handle_loops_and_finally_ex(zend_long depth) /* {{{ */ SET_UNUSED(opline->op1); 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)); + opline->opcode = ZEND_DISCARD_EXCEPTION; + opline->op1_type = IS_TMP_VAR; + opline->op1.var = loop_var->var_num; + SET_UNUSED(opline->op2); } else if (loop_var->opcode == ZEND_RETURN) { /* Stack separator */ break; @@ -4057,12 +4064,6 @@ void zend_compile_return(zend_ast *ast) /* {{{ */ zend_compile_expr(&expr_node, expr_ast); } - if (CG(context).in_finally) { - opline = zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL); - opline->op1_type = IS_TMP_VAR; - 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); @@ -4573,6 +4574,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */ uint32_t try_catch_offset; uint32_t *jmp_opnums = safe_emalloc(sizeof(uint32_t), catches->children, 0); uint32_t orig_fast_call_var = CG(context).fast_call_var; + uint32_t orig_try_catch_offset = CG(context).try_catch_offset; if (catches->children == 0 && !finally_ast) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally"); @@ -4606,6 +4608,8 @@ void zend_compile_try(zend_ast *ast) /* {{{ */ zend_stack_push(&CG(loop_var_stack), &fast_call); } + CG(context).try_catch_offset = try_catch_offset; + zend_compile_stmt(try_ast); if (catches->children != 0) { @@ -4679,11 +4683,18 @@ void zend_compile_try(zend_ast *ast) /* {{{ */ } if (finally_ast) { + zend_loop_var discard_exception; uint32_t opnum_jmp = get_next_op_number(CG(active_op_array)) + 1; /* Pop FAST_CALL from unwind stack */ zend_stack_del_top(&CG(loop_var_stack)); + /* Push DISCARD_EXCEPTION on unwind stack */ + discard_exception.opcode = ZEND_DISCARD_EXCEPTION; + discard_exception.var_type = IS_TMP_VAR; + discard_exception.var_num = CG(context).fast_call_var; + zend_stack_push(&CG(loop_var_stack), &discard_exception); + CG(zend_lineno) = finally_ast->lineno; opline = zend_emit_op(NULL, ZEND_FAST_CALL, NULL, NULL); @@ -4704,12 +4715,18 @@ void zend_compile_try(zend_ast *ast) /* {{{ */ opline = zend_emit_op(NULL, ZEND_FAST_RET, NULL, NULL); opline->op1_type = IS_TMP_VAR; opline->op1.var = CG(context).fast_call_var; + opline->op2.num = orig_try_catch_offset; zend_update_jump_target_to_next(opnum_jmp); CG(context).fast_call_var = orig_fast_call_var; + + /* Pop DISCARD_EXCEPTION from unwind stack */ + zend_stack_del_top(&CG(loop_var_stack)); } + CG(context).try_catch_offset = orig_try_catch_offset; + efree(jmp_opnums); } /* }}} */ |
