Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Refactor examing of jumping out of finally block

  • Loading branch information...
commit f2a8912e618d4bd8ff5be266e37f2b6e2280e994 1 parent 2449365
Xinchen Hui laruence authored
2  Zend/tests/try_finally_005.phpt
View
@@ -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
14 Zend/tests/try_finally_006.phpt
View
@@ -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
22 Zend/tests/try_finally_007.phpt
View
@@ -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
24 Zend/tests/try_finally_008.phpt
View
@@ -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
30 Zend/zend_compile.c
View
@@ -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);
3  Zend/zend_compile.h
View
@@ -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
17 Zend/zend_opcode.c
View
@@ -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:
Please sign in to comment.
Something went wrong with that request. Please try again.