diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | Zend/tests/bug69221.phpt | 24 | ||||
-rw-r--r-- | Zend/tests/bug69221_2.phpt | 20 | ||||
-rw-r--r-- | Zend/zend_generators.c | 8 | ||||
-rw-r--r-- | Zend/zend_generators.h | 6 |
5 files changed, 53 insertions, 7 deletions
@@ -10,6 +10,8 @@ PHP NEWS . Fixed bug #68917 (parse_url fails on some partial urls). (Wei Dai) . Fixed bug #69212 (Leaking VIA_HANDLER func when exception thrown in __call/... arg passing). (Nikita) + . Fixed bug #69221 (Segmentation fault when using a generator in combination + with an Iterator). (Nikita) - Filter: . Fixed bug #69202: (FILTER_FLAG_STRIP_BACKTICK ignored unless other diff --git a/Zend/tests/bug69221.phpt b/Zend/tests/bug69221.phpt new file mode 100644 index 0000000000..9eb5afcad8 --- /dev/null +++ b/Zend/tests/bug69221.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #69221: Segmentation fault when using a generator in combination with an Iterator +--FILE-- +<?php + +function gen() { + yield 1; +}; + +$gen1 = gen(); +$gen2 = (object) $gen1; + +foreach ($gen1 as $v1) { + foreach ($gen2 as $v2) { + break 2; + } +} + +unset($gen1); +foreach ($gen2 as $v) { var_dump($v); } + +?> +--EXPECTF-- +int(1) diff --git a/Zend/tests/bug69221_2.phpt b/Zend/tests/bug69221_2.phpt new file mode 100644 index 0000000000..f3805b81c1 --- /dev/null +++ b/Zend/tests/bug69221_2.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #69221: Segmentation fault when using a generator in combination with an Iterator (2) +--FILE-- +<?php + +$gen = function() { + yield 1; +}; + +$iter = new IteratorIterator($gen()); +$ngen = $iter->getInnerIterator(); + +var_dump(iterator_to_array($ngen, false)); + +?> +--EXPECT-- +array(1) { + [0]=> + int(1) +} diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index c96d1e979b..b457f56463 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -605,9 +605,9 @@ ZEND_METHOD(Generator, __wakeup) static void zend_generator_iterator_dtor(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */ { - zval *object = ((zend_generator_iterator *) iterator)->object; + zend_generator_iterator *iter = (zend_generator_iterator *) iterator; - zval_ptr_dtor(&object); + zend_objects_store_del_ref_by_handle(iter->handle TSRMLS_CC); } /* }}} */ @@ -699,8 +699,8 @@ zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *ob /* We have to keep a reference to the generator object zval around, * otherwise the generator may be destroyed during iteration. */ - Z_ADDREF_P(object); - iterator->object = object; + iterator->handle = Z_OBJ_HANDLE_P(object); + zend_objects_store_add_ref_by_handle(iterator->handle TSRMLS_CC); return (zend_object_iterator *) iterator; } diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index d460c908ad..061ea518cd 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -28,9 +28,9 @@ extern ZEND_API zend_class_entry *zend_ce_generator; typedef struct _zend_generator_iterator { zend_object_iterator intern; - /* The generator object zval has to be stored, because the iterator is - * holding a ref to it, which has to be dtored. */ - zval *object; + /* The generator object handle has to be stored, because the + * iterator is holding a ref to it, which has to be dtored. */ + zend_object_handle handle; } zend_generator_iterator; typedef struct _zend_generator { |