]> granicus.if.org Git - php/commitdiff
Prevents `goto` out of a finally block
authorXinchen Hui <laruence@php.net>
Thu, 16 Aug 2012 10:17:26 +0000 (18:17 +0800)
committerXinchen Hui <laruence@php.net>
Thu, 16 Aug 2012 10:17:26 +0000 (18:17 +0800)
Zend/tests/try_finally_005.phpt [new file with mode: 0644]
Zend/tests/try_finally_006.phpt [new file with mode: 0644]
Zend/zend_compile.c

diff --git a/Zend/tests/try_finally_005.phpt b/Zend/tests/try_finally_005.phpt
new file mode 100644 (file)
index 0000000..e0937f1
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Finally with long goto
+--FILE--
+<?php
+function foo () {
+   try {
+   } finally {
+      goto label;
+   }
+label:
+   return 1;
+}
+
+foo();
+?>
+--EXPECTF--
+Fatal error: 'goto' 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
new file mode 100644 (file)
index 0000000..ba1c183
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+Finally with near goto
+--FILE--
+<?php
+function foo () {
+   try {
+   } finally {
+      goto label;
+      echo "dummy";
+label:
+      echo "label";
+   }
+}
+
+foo();
+?>
+--EXPECTF--
+label
index 48b85f0b7091c9d646404f29e9b862ca9325b547..378cf17bffabf9b79e431830a6c26fa288598002 100644 (file)
@@ -2277,6 +2277,25 @@ 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 - CG(active_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) {
+                                               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++) {