]> granicus.if.org Git - php/commitdiff
Fixed bug #79927
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 11 Aug 2020 13:48:40 +0000 (15:48 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 11 Aug 2020 13:48:40 +0000 (15:48 +0200)
We need to unset the AT_FIRST_YIELD flag when yielding from an
array as well.

In the interest of being conservative, I'm applying this only to
PHP 8.

NEWS
Zend/tests/bug79927.phpt [new file with mode: 0644]
Zend/zend_generators.c

diff --git a/NEWS b/NEWS
index c890b29c9a276677a06656c9aa37efe6f662b9b9..cd163a5f6cc34b71eba84151f5c8af6dcde8d284 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,8 @@ PHP                                                                        NEWS
     exit value in CLI). (Nikita)
   . Fixed bug #62294 (register_shutdown_function() does not correctly handle
     exit code). (Nikita)
+  . Fixed bug #79927 (Generator doesn't throw exception after multiple yield
+    from iterable). (Nikita)
 
 - Date:
   . Fixed bug #60302 (DateTime::createFromFormat should new static(), not new
diff --git a/Zend/tests/bug79927.phpt b/Zend/tests/bug79927.phpt
new file mode 100644 (file)
index 0000000..df8f245
--- /dev/null
@@ -0,0 +1,31 @@
+--TEST--
+Bug #79927: Generator doesn't throw exception after multiple yield from iterable
+--FILE--
+<?php
+
+$generator = (function () {
+    yield from [1, 2, 3];
+})();
+
+$generator->next();
+$generator->next();
+try {
+    $generator->rewind();
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+echo $generator->current(), "\n";
+
+$generator2 = (function () {
+    yield from [];
+    yield 4;
+})();
+$generator2->current();
+$generator2->rewind();
+echo $generator2->current(), "\n";
+
+?>
+--EXPECT--
+Cannot rewind a generator that was already run
+3
+4
index 0d2d7e4a4d9563ffdbe8da53ee0c26cc82e2c8f2..040a213ce7491288d783ff5156ca0b236213f9ba 100644 (file)
@@ -731,6 +731,9 @@ try_again:
                return;
        }
 
+       /* Drop the AT_FIRST_YIELD flag */
+       orig_generator->flags &= ~ZEND_GENERATOR_AT_FIRST_YIELD;
+
        if (UNEXPECTED(!Z_ISUNDEF(generator->values))) {
                if (EXPECTED(zend_generator_get_next_delegated_value(generator) == SUCCESS)) {
                        orig_generator->flags &= ~ZEND_GENERATOR_DO_INIT;
@@ -740,9 +743,6 @@ try_again:
                 * after the "yield from" expression. */
        }
 
-       /* Drop the AT_FIRST_YIELD flag */
-       orig_generator->flags &= ~ZEND_GENERATOR_AT_FIRST_YIELD;
-
        {
                /* Backup executor globals */
                zend_execute_data *original_execute_data = EG(current_execute_data);