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

Reply via email to