From: Xinchen Hui Date: Fri, 17 Aug 2012 16:16:34 +0000 (+0800) Subject: Refactor examing of jumping out of finally block X-Git-Tag: php-5.5.0alpha1~20^2~61 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f2a8912e618d4bd8ff5be266e37f2b6e2280e994;p=php Refactor examing of jumping out of finally block --- diff --git a/Zend/tests/try_finally_005.phpt b/Zend/tests/try_finally_005.phpt index e0937f1b16..2c6c2c9e6c 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 ba1c183eb4..2bfa4caea9 100644 --- a/Zend/tests/try_finally_006.phpt +++ b/Zend/tests/try_finally_006.phpt @@ -3,12 +3,19 @@ Finally with near goto --FILE-- --EXPECTF-- label +okey diff --git a/Zend/tests/try_finally_007.phpt b/Zend/tests/try_finally_007.phpt new file mode 100644 index 0000000000..b13bd59e50 --- /dev/null +++ b/Zend/tests/try_finally_007.phpt @@ -0,0 +1,22 @@ +--TEST-- +Finally with goto previous label +--FILE-- + +--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 0000000000..77ecf4fdee --- /dev/null +++ b/Zend/tests/try_finally_008.phpt @@ -0,0 +1,24 @@ +--TEST-- +Finally with jmp (do while) +--FILE-- + +--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 bad9411a2f..6a501f78a5 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; ilast_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 550fb0e931..a06c985a97 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 19fd71e763..8cccfe6376 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: