]> granicus.if.org Git - php/commitdiff
Fix bug #69458
authorBob Weinand <bobwei9@hotmail.com>
Wed, 15 Apr 2015 19:56:11 +0000 (21:56 +0200)
committerBob Weinand <bobwei9@hotmail.com>
Wed, 15 Apr 2015 19:56:11 +0000 (21:56 +0200)
Zend/tests/generators/yield_from_already_running.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/generators/yield_from_already_running.phpt b/Zend/tests/generators/yield_from_already_running.phpt
new file mode 100644 (file)
index 0000000..789490c
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+Yielding from the already running Generator should fail (bug #69458)
+--FILE--
+<?php
+
+function gen() {
+       yield from yield;
+}
+
+($gen = gen())->send($gen);
+
+?>
+--EXPECTF--
+Fatal error: Impossible to yield from the Generator being currently run in %s on line %d
index a2f7ace870ccd12274c9bc519217103da21db8dc..f4bd4988324c0ec5afe53383243b526f894c19d6 100644 (file)
@@ -7389,8 +7389,15 @@ ZEND_VM_HANDLER(142, ZEND_YIELD_FROM, CONST|TMP|VAR|CV, ANY)
                        FREE_OP1_IF_VAR();
 
                        if (Z_ISUNDEF(new_gen->retval)) {
-                               zend_generator_yield_from(generator, new_gen);
-                       } else if (new_gen->execute_data == NULL) {
+                               if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) {
+                                       zend_error(E_ERROR | E_EXCEPTION, "Impossible to yield from the Generator being currently run");
+
+                                       HANDLE_EXCEPTION();
+                                       ZEND_VM_NEXT_OPCODE();
+                               } else {
+                                       zend_generator_yield_from(generator, new_gen);
+                               }
+                       } else if (UNEXPECTED(new_gen->execute_data == NULL)) {
                                zend_error(E_ERROR | E_EXCEPTION, "Generator passed to yield from was aborted without proper return and is unable to continue");
 
                                HANDLE_EXCEPTION();
index 457de3dd9f94585e6b8e6553399f0909bbf069ec..94ed61d7c7d095887da30e0872fcea2829872803 100644 (file)
@@ -4045,8 +4045,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER(
                        }
 
                        if (Z_ISUNDEF(new_gen->retval)) {
-                               zend_generator_yield_from(generator, new_gen);
-                       } else if (new_gen->execute_data == NULL) {
+                               if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) {
+                                       zend_error(E_ERROR | E_EXCEPTION, "Impossible to yield from the Generator being currently run");
+
+                                       HANDLE_EXCEPTION();
+                                       ZEND_VM_NEXT_OPCODE();
+                               } else {
+                                       zend_generator_yield_from(generator, new_gen);
+                               }
+                       } else if (UNEXPECTED(new_gen->execute_data == NULL)) {
                                zend_error(E_ERROR | E_EXCEPTION, "Generator passed to yield from was aborted without proper return and is unable to continue");
 
                                HANDLE_EXCEPTION();
@@ -11678,8 +11685,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_TMP_HANDLER(ZE
                        }
 
                        if (Z_ISUNDEF(new_gen->retval)) {
-                               zend_generator_yield_from(generator, new_gen);
-                       } else if (new_gen->execute_data == NULL) {
+                               if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) {
+                                       zend_error(E_ERROR | E_EXCEPTION, "Impossible to yield from the Generator being currently run");
+
+                                       HANDLE_EXCEPTION();
+                                       ZEND_VM_NEXT_OPCODE();
+                               } else {
+                                       zend_generator_yield_from(generator, new_gen);
+                               }
+                       } else if (UNEXPECTED(new_gen->execute_data == NULL)) {
                                zend_error(E_ERROR | E_EXCEPTION, "Generator passed to yield from was aborted without proper return and is unable to continue");
 
                                HANDLE_EXCEPTION();
@@ -15377,8 +15391,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_VAR_HANDLER(ZE
                        zval_ptr_dtor_nogc(free_op1);
 
                        if (Z_ISUNDEF(new_gen->retval)) {
-                               zend_generator_yield_from(generator, new_gen);
-                       } else if (new_gen->execute_data == NULL) {
+                               if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) {
+                                       zend_error(E_ERROR | E_EXCEPTION, "Impossible to yield from the Generator being currently run");
+
+                                       HANDLE_EXCEPTION();
+                                       ZEND_VM_NEXT_OPCODE();
+                               } else {
+                                       zend_generator_yield_from(generator, new_gen);
+                               }
+                       } else if (UNEXPECTED(new_gen->execute_data == NULL)) {
                                zend_error(E_ERROR | E_EXCEPTION, "Generator passed to yield from was aborted without proper return and is unable to continue");
 
                                HANDLE_EXCEPTION();
@@ -28967,8 +28988,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN
                        }
 
                        if (Z_ISUNDEF(new_gen->retval)) {
-                               zend_generator_yield_from(generator, new_gen);
-                       } else if (new_gen->execute_data == NULL) {
+                               if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) {
+                                       zend_error(E_ERROR | E_EXCEPTION, "Impossible to yield from the Generator being currently run");
+
+                                       HANDLE_EXCEPTION();
+                                       ZEND_VM_NEXT_OPCODE();
+                               } else {
+                                       zend_generator_yield_from(generator, new_gen);
+                               }
+                       } else if (UNEXPECTED(new_gen->execute_data == NULL)) {
                                zend_error(E_ERROR | E_EXCEPTION, "Generator passed to yield from was aborted without proper return and is unable to continue");
 
                                HANDLE_EXCEPTION();