Commit:    72b9b8f380690357fc29efdfcba183b8a8a81268
Author:    Xinchen Hui <larue...@php.net>         Sat, 18 Aug 2012 11:44:09 
+0800
Parents:   7cf9ac1420ecb1b05a7899e50e91772afe3fcdfb
Branches:  master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=72b9b8f380690357fc29efdfcba183b8a8a81268

Log:
Make the codes clearer, and also check continue statement

Changed paths:
  M  Zend/tests/try_finally_008.phpt
  A  Zend/tests/try_finally_009.phpt
  M  Zend/zend_opcode.c
  M  Zend/zend_vm_def.h
  M  Zend/zend_vm_execute.h


Diff:
diff --git a/Zend/tests/try_finally_008.phpt b/Zend/tests/try_finally_008.phpt
index 77ecf4f..9025d88 100644
--- a/Zend/tests/try_finally_008.phpt
+++ b/Zend/tests/try_finally_008.phpt
@@ -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
index 0000000..7c3da67
--- /dev/null
+++ b/Zend/tests/try_finally_009.phpt
@@ -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
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 8cccfe6..86144d6 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -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;
@@ -529,23 +547,29 @@ 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:
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 17dfb5f..1da4c12 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -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);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 6fd7f07..b5a649d 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -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);


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to