]> granicus.if.org Git - php/commitdiff
Make the codes clearer, and also check continue statement
authorXinchen Hui <laruence@php.net>
Sat, 18 Aug 2012 03:44:09 +0000 (11:44 +0800)
committerXinchen Hui <laruence@php.net>
Sat, 18 Aug 2012 03:44:09 +0000 (11:44 +0800)
Zend/tests/try_finally_008.phpt
Zend/tests/try_finally_009.phpt [new file with mode: 0644]
Zend/zend_opcode.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 77ecf4fdeeece729935a97759ffa581c27f299ef..9025d8824dac364be40629249ba5679315214020 100644 (file)
@@ -7,15 +7,12 @@ function foo () {
         try {
             try {
             } finally {
-                goto label;
-                echo "dummy";
+                break;
             }
         } catch (Exception $e) {
         } finally {
         }
     } while (0);
-label:
-        echo "label"; 
 }
 
 foo();
diff --git a/Zend/tests/try_finally_009.phpt b/Zend/tests/try_finally_009.phpt
new file mode 100644 (file)
index 0000000..7c3da67
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+Finally with jmp (for continue)
+--FILE--
+<?php
+function foo () {
+    for($i = 0; $i < 5; $i++) {
+        do {
+            try {
+                try {
+                } finally {
+                }
+            } catch (Exception $e) {
+            } finally {
+              continue;
+            }
+        } while (0);
+    }
+}
+
+foo();
+?>
+--EXPECTF--
+Fatal error: jump out of a finally block is disallowed in %stry_finally_009.php on line %d
index 8cccfe637684cd0053507859f2a4adc62d7caa4e..86144d60e18ff62c18a322fde2e9126b7f45084e 100644 (file)
@@ -485,6 +485,24 @@ static void zend_extension_op_array_handler(zend_extension *extension, zend_op_a
        }
 }
 
+static void zend_check_finally_breakout(zend_op_array *op_array, zend_op *opline, zend_uint dst_num TSRMLS_DC) {
+       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)
+                               && (dst_num >= op_array->try_catch_array[i].finally_end 
+                                       || dst_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");
+               }
+       } 
+}
+
 ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
 {
        zend_op *opline, *end;
@@ -528,24 +546,30 @@ 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_check_finally_breakout(op_array, opline, opline->op1.opline_num TSRMLS_CC);
+                               }
+                               opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
+                               break;
+            case ZEND_BRK:
+            case ZEND_CONT:
                                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;
+                                       int nest_levels, array_offset;
+                                       zend_brk_cont_element *jmp_to;
+
+                                       nest_levels = Z_LVAL_P(opline->op2.zv);
+                                       array_offset = opline->op1.opline_num;
+                                       do {
+                                               jmp_to = &op_array->brk_cont_array[array_offset];
+                                               if (nest_levels > 1) {
+                                                       array_offset = jmp_to->parent;
                                                }
-                                               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");
-                                               }
-                                       } 
+                                       } while (--nest_levels > 0);
+                                       if (op_array->last_try_catch) {
+                                               zend_check_finally_breakout(op_array, opline, jmp_to->brk TSRMLS_CC);
+                                       }
                                }
-                               opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
                                break;
                        case ZEND_JMPZ:
                        case ZEND_JMPNZ:
index 17dfb5fd81b56c90fe38b804fda45efa58e9c65e..1da4c12440a38f270f39edad6635b7fa646ff623 100644 (file)
@@ -5317,10 +5317,10 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED)
        ZEND_VM_NEXT_OPCODE();
 }
 
-ZEND_VM_HANDLER(159, ZEND_LEAVE, ANY, ANY) {
-       {
+ZEND_VM_HANDLER(159, ZEND_LEAVE, ANY, ANY)
+{
        USE_OPLINE
-               zend_uint i, op_num = opline - EG(active_op_array)->opcodes;
+       zend_uint i, op_num = opline - EG(active_op_array)->opcodes;
 
        SAVE_OPLINE();
        zend_exception_restore(TSRMLS_C);
index 6fd7f0790dc63037f69f697633a2f680c381c1cc..b5a649d0a27326b80102cebabdfc1f75f6042189 100644 (file)
@@ -1176,9 +1176,9 @@ static int ZEND_FASTCALL  ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
 }
 
 static int ZEND_FASTCALL  ZEND_LEAVE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-       {
+{
        USE_OPLINE
-               zend_uint i, op_num = opline - EG(active_op_array)->opcodes;
+       zend_uint i, op_num = opline - EG(active_op_array)->opcodes;
 
        SAVE_OPLINE();
        zend_exception_restore(TSRMLS_C);