From: Nikita Popov Date: Wed, 29 Aug 2012 18:46:56 +0000 (+0200) Subject: Fix segfault when traversing a by-ref generator twice X-Git-Tag: php-5.5.0alpha1~20^2~24^2~24^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bef79588d543db996d092191ac498751a1cc161f;p=php Fix segfault when traversing a by-ref generator twice If you try to traverse an already closed generator an exception will now be thrown. Furthermore this changes the error for traversing a by-val generator by-ref from an E_ERROR to an Exception. --- diff --git a/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt b/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt index 9c618d2515..de5b22f6ba 100644 --- a/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt +++ b/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt @@ -10,4 +10,9 @@ foreach ($gen as &$value) { } ?> --EXPECTF-- -Fatal error: You can only iterate a generator by-reference if it declared that it yields by-reference in %s on line %d +Fatal error: Uncaught exception 'Exception' with message 'You can only iterate a generator by-reference if it declared that it yields by-reference' in %s:%d +Stack trace: +#0 %s(%d): unknown() +#1 {main} + thrown in %s on line %d + diff --git a/Zend/tests/generators/generator_rewind.phpt b/Zend/tests/generators/generator_rewind.phpt index af885ef382..c4b5bbbdf4 100644 --- a/Zend/tests/generators/generator_rewind.phpt +++ b/Zend/tests/generators/generator_rewind.phpt @@ -21,21 +21,27 @@ try { echo "\n", $e, "\n\n"; } -$gen = gen(); +function &gen2() { + $foo = 'bar'; + yield $foo; + yield $foo; +} + +$gen = gen2(); foreach ($gen as $v) { } try { foreach ($gen as $v) { } } catch (Exception $e) { - echo "\n", $e, "\n\n"; + echo $e, "\n\n"; } -function gen2() { +function gen3() { echo "in generator\n"; if (false) yield; } -$gen = gen2(); +$gen = gen3(); $gen->rewind(); ?> @@ -48,10 +54,7 @@ Stack trace: #0 %s(%d): Generator->rewind() #1 {main} -before yield -after yield - -exception 'Exception' with message 'Cannot rewind a generator that was already run' in %s:%d +exception 'Exception' with message 'Cannot traverse an already closed generator' in %s:%d Stack trace: #0 %s(%d): unknown() #1 {main} diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 0eb17d0293..60fa8b6491 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -766,8 +766,14 @@ zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *ob generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); + if (!generator->execute_data) { + zend_throw_exception(NULL, "Cannot traverse an already closed generator", 0 TSRMLS_CC); + return NULL; + } + if (by_ref && !(generator->execute_data->op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) { - zend_error(E_ERROR, "You can only iterate a generator by-reference if it declared that it yields by-reference"); + zend_throw_exception(NULL, "You can only iterate a generator by-reference if it declared that it yields by-reference", 0 TSRMLS_CC); + return NULL; } iterator = emalloc(sizeof(zend_generator_iterator));