Commit: 3ee20e450fb5e52f68174f982fbd4f13eb2d9beb Author: Nikita Popov <ni...@php.net> Fri, 1 Feb 2013 18:33:26 +0100 Parents: ac18c318dc4af08074a56cf706678a2457495944 Branches: PHP-5.5 master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=3ee20e450fb5e52f68174f982fbd4f13eb2d9beb Log: Fix segfault when cloning generator with properties Rule of thumb: Always implement the object clone handler rather than the object storage clone handler. Actually I think we should drop the latter. It's nearly never usable. Changed paths: A Zend/tests/generators/clone_with_properties.phpt M Zend/zend_generators.c Diff: diff --git a/Zend/tests/generators/clone_with_properties.phpt b/Zend/tests/generators/clone_with_properties.phpt new file mode 100644 index 0000000..900253c --- /dev/null +++ b/Zend/tests/generators/clone_with_properties.phpt @@ -0,0 +1,18 @@ +--TEST-- +Tests cloning a generator with properties +--FILE-- +<?php + +function gen() { yield; } + +$g1 = gen(); +$g1->prop = 'val'; + +$g2 = clone $g1; +unset($g1); + +var_dump($g2->prop); + +?> +--EXPECT-- +string(3) "val" diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index e8787d5..6213206 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -27,6 +27,8 @@ ZEND_API zend_class_entry *zend_ce_generator; static zend_object_handlers zend_generator_handlers; +static zend_object_value zend_generator_create(zend_class_entry *class_type TSRMLS_DC); + ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC) /* {{{ */ { if (generator->value) { @@ -188,10 +190,19 @@ static void zend_generator_free_storage(zend_generator *generator TSRMLS_DC) /* } /* }}} */ -static void zend_generator_clone_storage(zend_generator *orig, zend_generator **clone_ptr TSRMLS_DC) /* {{{ */ +static zend_object_value zend_generator_clone(zval *object TSRMLS_DC) /* {{{ */ { - zend_generator *clone = emalloc(sizeof(zend_generator)); - memcpy(clone, orig, sizeof(zend_generator)); + zend_generator *orig = zend_object_store_get_object(object TSRMLS_CC); + zend_object_value clone_val = zend_generator_create(Z_OBJCE_P(object) TSRMLS_CC); + zend_generator *clone = zend_object_store_get_object_by_handle(clone_val.handle TSRMLS_CC); + + zend_objects_clone_members( + &clone->std, clone_val, &orig->std, Z_OBJ_HANDLE_P(object) TSRMLS_CC + ); + + clone->execute_data = orig->execute_data; + clone->largest_used_integer_key = orig->largest_used_integer_key; + clone->flags = orig->flags; if (orig->execute_data) { /* Create a few shorter aliases to the old execution data */ @@ -335,14 +346,16 @@ static void zend_generator_clone_storage(zend_generator *orig, zend_generator ** /* The value and key are known not to be references, so simply add refs */ if (orig->value) { + clone->value = orig->value; Z_ADDREF_P(orig->value); } if (orig->key) { + clone->key = orig->key; Z_ADDREF_P(orig->key); } - *clone_ptr = clone; + return clone_val; } /* }}} */ @@ -362,8 +375,7 @@ static zend_object_value zend_generator_create(zend_class_entry *class_type TSRM object.handle = zend_objects_store_put(generator, (zend_objects_store_dtor_t) zend_generator_dtor_storage, (zend_objects_free_object_storage_t) zend_generator_free_storage, - (zend_objects_store_clone_t) zend_generator_clone_storage - TSRMLS_CC + NULL TSRMLS_CC ); object.handlers = &zend_generator_handlers; @@ -863,7 +875,7 @@ void zend_register_generator_ce(TSRMLS_D) /* {{{ */ memcpy(&zend_generator_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); zend_generator_handlers.get_constructor = zend_generator_get_constructor; - zend_generator_handlers.clone_obj = zend_objects_store_clone_obj; + zend_generator_handlers.clone_obj = zend_generator_clone; } /* }}} */ -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php