Permalink
Browse files

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.
  • Loading branch information...
1 parent cc07038 commit bef79588d543db996d092191ac498751a1cc161f @nikic nikic committed Aug 29, 2012
@@ -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
+
@@ -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}
@@ -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));

0 comments on commit bef7958

Please sign in to comment.