Commit:    bef79588d543db996d092191ac498751a1cc161f
Author:    Nikita Popov <ni...@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));


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to