From cb9c4bc3d42b574bdb1cc1017d0f714772cbd897 Mon Sep 17 00:00:00 2001 From: Takuya Aramaki Date: Wed, 1 Jan 2025 22:20:17 +0900 Subject: [PATCH] Fix GH-11591: AppendIterator fails to iterate with an empty generator --- Zend/zend_generators.c | 9 --------- Zend/zend_generators.h | 8 ++++++++ ext/spl/spl_iterators.c | 10 ++++++++++ ext/spl/tests/gh11591.phpt | 17 +++++++++++++++++ 4 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 ext/spl/tests/gh11591.phpt diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index a6ea91a7425b9..d8673e7b81336 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -872,15 +872,6 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */ } /* }}} */ -static inline void zend_generator_ensure_initialized(zend_generator *generator) /* {{{ */ -{ - if (UNEXPECTED(Z_TYPE(generator->value) == IS_UNDEF) && EXPECTED(generator->execute_data) && EXPECTED(generator->node.parent == NULL)) { - zend_generator_resume(generator); - generator->flags |= ZEND_GENERATOR_AT_FIRST_YIELD; - } -} -/* }}} */ - static inline void zend_generator_rewind(zend_generator *generator) /* {{{ */ { zend_generator_ensure_initialized(generator); diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index e7b01fb20ad7f..b3eef02b6948c 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -105,6 +105,14 @@ static const uint8_t ZEND_GENERATOR_IN_FIBER = 0x10; void zend_register_generator_ce(void); ZEND_API void zend_generator_close(zend_generator *generator, bool finished_execution); ZEND_API void zend_generator_resume(zend_generator *generator); +static inline void zend_generator_ensure_initialized(zend_generator *generator) /* {{{ */ +{ + if (UNEXPECTED(Z_TYPE(generator->value) == IS_UNDEF) && EXPECTED(generator->execute_data) && EXPECTED(generator->node.parent == NULL)) { + zend_generator_resume(generator); + generator->flags |= ZEND_GENERATOR_AT_FIRST_YIELD; + } +} +/* }}} */ ZEND_API void zend_generator_restore_call_stack(zend_generator *generator); ZEND_API zend_execute_data* zend_generator_freeze_call_stack(zend_execute_data *execute_data); diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index d4e40bf6b684a..88c25b7ce69c4 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -21,6 +21,7 @@ #include "php.h" #include "zend_exceptions.h" #include "zend_interfaces.h" +#include "zend_generators.h" #include "ext/pcre/php_pcre.h" #include "spl_iterators.h" @@ -2814,6 +2815,15 @@ PHP_METHOD(AppendIterator, append) RETURN_THROWS(); } + if (instanceof_function(Z_OBJCE_P(it), zend_ce_generator)) { + zend_generator *gen = (zend_generator*)Z_OBJ_P(it); + zend_generator_ensure_initialized(gen); + if (gen->execute_data == NULL) { + /* Skip an empty generator */ + return; + } + } + SPL_FETCH_AND_CHECK_DUAL_IT(intern, ZEND_THIS); if (intern->u.append.iterator->funcs->valid(intern->u.append.iterator) == SUCCESS && spl_dual_it_valid(intern) != SUCCESS) { diff --git a/ext/spl/tests/gh11591.phpt b/ext/spl/tests/gh11591.phpt new file mode 100644 index 0000000000000..8c690c2ce915b --- /dev/null +++ b/ext/spl/tests/gh11591.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug GH-11591 (Inconsistent behaviour with AppendIterator and empty generators) +--FILE-- +append(yieldEmpty()); + +foreach ($iterator as $item) { + var_dump($item); +} +?> +--EXPECT--