]> granicus.if.org Git - php/commitdiff
Fixed bug #71441 (Typehinted Generator with return in try/finally crashes)
authorBob Weinand <bobwei9@hotmail.com>
Sun, 24 Jan 2016 18:55:16 +0000 (19:55 +0100)
committerBob Weinand <bobwei9@hotmail.com>
Sun, 24 Jan 2016 18:55:16 +0000 (19:55 +0100)
NEWS
Zend/tests/generators/bug71441.phpt [new file with mode: 0644]
Zend/zend_opcode.c

diff --git a/NEWS b/NEWS
index 0010f31bb384de78e83576fb8f9c6658b1f6fa40..65bd694d7b83f3cc7ddae6f3d28a3aac12d06191 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,9 @@ PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 2016 PHP 7.0.4
 
-
+- Core:
+  . Fixed bug #71441 (Typehinted Generator with return in try/finally crashes).
+    (Bob)
 
 04 Feb 2016 PHP 7.0.3
 
diff --git a/Zend/tests/generators/bug71441.phpt b/Zend/tests/generators/bug71441.phpt
new file mode 100644 (file)
index 0000000..3a10388
--- /dev/null
@@ -0,0 +1,29 @@
+--TEST--
+Bug #71441 (Typehinted Generator with return in try/finally crashes)
+--FILE--
+<?php
+
+$num = 2000; /* to be sure to be in wild memory */
+$add = str_repeat("1 +", $num);
+$gen = (eval(<<<PHP
+return function (): \Generator {
+       try {
+               \$a = 1;
+               \$foo = \$a + $add \$a;
+               return yield \$foo;
+       } finally {
+               print "Ok\n";
+       }
+};
+PHP
+))();
+var_dump($gen->current());
+$gen->send("Success");
+var_dump($gen->getReturn());
+
+?>
+--EXPECT--
+int(2002)
+Ok
+string(7) "Success"
+
index dee54ba14cb478b42f22c9a2c39e72bebe6c7576..2cf32b9c0a14d6caa9379026175089a209cd98db 100644 (file)
@@ -668,9 +668,13 @@ ZEND_API int pass_two(zend_op_array *op_array)
                        case ZEND_VERIFY_RETURN_TYPE:
                                if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
                                        if (opline->op1_type != IS_UNUSED) {
-                                               (opline + 1)->op1 = opline->op1;
-                                               (opline + 1)->op1_type = opline->op1_type;
+                                               zend_op *ret = opline;
+                                               do ret++; while (ret->opcode != ZEND_RETURN);
+
+                                               ret->op1 = opline->op1;
+                                               ret->op1_type = opline->op1_type;
                                        }
+
                                        MAKE_NOP(opline);
                                }
                                break;