Commit: f2a8912e618d4bd8ff5be266e37f2b6e2280e994 Author: Xinchen Hui <larue...@php.net> Sat, 18 Aug 2012 00:16:34 +0800 Parents: 24493652382c985b13a9ed94aae5fffae16a6895 Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=f2a8912e618d4bd8ff5be266e37f2b6e2280e994 Log: Refactor examing of jumping out of finally block Changed paths: M Zend/tests/try_finally_005.phpt M Zend/tests/try_finally_006.phpt A Zend/tests/try_finally_007.phpt A Zend/tests/try_finally_008.phpt M Zend/zend_compile.c M Zend/zend_compile.h M Zend/zend_opcode.c Diff: diff --git a/Zend/tests/try_finally_005.phpt b/Zend/tests/try_finally_005.phpt index e0937f1..2c6c2c9 100644 --- a/Zend/tests/try_finally_005.phpt +++ b/Zend/tests/try_finally_005.phpt @@ -14,4 +14,4 @@ label: foo(); ?> --EXPECTF-- -Fatal error: 'goto' out of a finally block is disallowed in %stry_finally_005.php on line %d +Fatal error: jump out of a finally block is disallowed in %stry_finally_005.php on line %d diff --git a/Zend/tests/try_finally_006.phpt b/Zend/tests/try_finally_006.phpt index ba1c183..2bfa4ca 100644 --- a/Zend/tests/try_finally_006.phpt +++ b/Zend/tests/try_finally_006.phpt @@ -3,12 +3,19 @@ Finally with near goto --FILE-- <?php function foo () { + $jmp = 1; try { } finally { - goto label; - echo "dummy"; +previous: + if ($jmp) { + goto label; + echo "dummy"; label: - echo "label"; + echo "label\n"; + $jmp = 0; + goto previous; + } + echo "okey"; } } @@ -16,3 +23,4 @@ foo(); ?> --EXPECTF-- label +okey diff --git a/Zend/tests/try_finally_007.phpt b/Zend/tests/try_finally_007.phpt new file mode 100644 index 0000000..b13bd59 --- /dev/null +++ b/Zend/tests/try_finally_007.phpt @@ -0,0 +1,22 @@ +--TEST-- +Finally with goto previous label +--FILE-- +<?php +function foo () { + try { +label: + echo "label"; + try { + } finally { + goto label; + echo "dummy"; + } + } catch (Exception $e) { + } finally { + } +} + +foo(); +?> +--EXPECTF-- +Fatal error: jump out of a finally block is disallowed in %stry_finally_007.php on line %d diff --git a/Zend/tests/try_finally_008.phpt b/Zend/tests/try_finally_008.phpt new file mode 100644 index 0000000..77ecf4f --- /dev/null +++ b/Zend/tests/try_finally_008.phpt @@ -0,0 +1,24 @@ +--TEST-- +Finally with jmp (do while) +--FILE-- +<?php +function foo () { + do { + try { + try { + } finally { + goto label; + echo "dummy"; + } + } catch (Exception $e) { + } finally { + } + } while (0); +label: + echo "label"; +} + +foo(); +?> +--EXPECTF-- +Fatal error: jump out of a finally block is disallowed in %stry_finally_008.php on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index bad9411..6a501f7 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2277,30 +2277,6 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 zval_dtor(label); Z_TYPE_P(label) = IS_NULL; - if (op_array->last_try_catch) { - zend_uint i, op_num = opline - op_array->opcodes; - for (i=0; i<op_array->last_try_catch; i++) { - if (op_array->try_catch_array[i].try_op > op_num) { - break; - } - if (op_num >= op_array->try_catch_array[i].finally_op) { - zend_op *p, *end; - p = opline; - end = op_array->opcodes + opline->op1.opline_num; - while (++p < end) { - if (p->opcode == ZEND_LEAVE) { - if (pass2) { - CG(in_compilation) = 1; - CG(active_op_array) = op_array; - CG(zend_lineno) = opline->lineno; - } - zend_error(E_COMPILE_ERROR, "'goto' out of a finally block is disallowed"); - } - } - } - } - } - /* Check that we are not moving into loop or switch */ current = opline->extended_value; for (distance = 0; current != dest->brk_cont; distance++) { @@ -2686,6 +2662,7 @@ static int zend_add_try_element(zend_uint try_op TSRMLS_DC) /* {{{ */ CG(active_op_array)->try_catch_array = erealloc(CG(active_op_array)->try_catch_array, sizeof(zend_try_catch_element)*CG(active_op_array)->last_try_catch); CG(active_op_array)->try_catch_array[try_catch_offset].try_op = try_op; CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = 0; + CG(active_op_array)->try_catch_array[try_catch_offset].finally_end = 0; return try_catch_offset; } /* }}} */ @@ -2808,14 +2785,13 @@ void zend_do_bind_catch(znode *try_token, znode *catch_token TSRMLS_DC) /* {{{ * void zend_do_end_finally(znode *try_token, znode* catch_token, znode *finally_token TSRMLS_DC) /* {{{ */ { - zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - if (catch_token->op_type == IS_UNUSED && finally_token->op_type == IS_UNUSED) { zend_error(E_COMPILE_ERROR, "Cannot use try without catch or finally"); } if (finally_token->op_type != IS_UNUSED) { + zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_op = finally_token->u.op.opline_num; - //try_token->u.op.opline_num = catch_token->u.op.opline_num; + CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_end = get_next_op_number(CG(active_op_array)); opline->opcode = ZEND_LEAVE; SET_UNUSED(opline->op1); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 550fb0e..a06c985 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -132,7 +132,8 @@ typedef struct _zend_label { typedef struct _zend_try_catch_element { zend_uint try_op; zend_uint catch_op; /* ketchup! */ - zend_uint finally_op; + zend_uint finally_op; + zend_uint finally_end; } zend_try_catch_element; #if SIZEOF_LONG == 8 diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 19fd71e..8cccfe6 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -528,6 +528,23 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) } /* break omitted intentionally */ case ZEND_JMP: + if (op_array->last_try_catch) { + zend_uint i, op_num = opline - op_array->opcodes; + for (i=0; i < op_array->last_try_catch; i++) { + if (op_array->try_catch_array[i].try_op > op_num) { + break; + } + if ((op_num >= op_array->try_catch_array[i].finally_op + && op_num < op_array->try_catch_array[i].finally_end) + && (opline->op1.opline_num >= op_array->try_catch_array[i].finally_end + || opline->op1.opline_num < op_array->try_catch_array[i].finally_op)) { + CG(in_compilation) = 1; + CG(active_op_array) = op_array; + CG(zend_lineno) = opline->lineno; + zend_error(E_COMPILE_ERROR, "jump out of a finally block is disallowed"); + } + } + } opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num]; break; case ZEND_JMPZ: -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php