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

Reply via email to