com php-src: Fix segfault when traversing a by-ref generator twice: Zend/tests/generators/errors/non_ref_generator_iterated _by_ref_error.phpt
Zend/tests/generators/generator_ rewind.phpt Zend/zend_generators.c
| From: | Gustavo André dos Santos Lopes | Date: | Wed, 29 Aug 2012 18:46:56 +0000 |
| Subject: | com php-src: Fix segfault when traversing a by-ref generator twice: Zend/tests/generators/errors/non_ref_generator_iterated _by_ref_error.phpt Zend/tests/generators/generator_ rewind.phpt Zend/zend_generators.c |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-70018@lists.php.net to get a copy of this message | ||
Commit: bef79588d543db996d092191ac498751a1cc161f
Author: Nikita Popov <nikic@php.net> Wed, 29 Aug 2012 20:46:56 +0200
Parents: cc07038fa9b2a59893c52fb0c515a1fb03e56d5c
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=bef79588d543db996d092191ac498751a1cc161f
Log:
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.
Changed paths:
M Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt
M Zend/tests/generators/generator_rewind.phpt
M Zend/zend_generators.c
Diff:
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 9c618d2..de5b22f 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 af885ef..c4b5bbb 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 0eb17d0..60fa8b6 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));