helly Tue Apr 4 19:53:21 2006 UTC Added files: (Branch: PHP_5_1) /php-src/ext/spl/tests array_022.phpt bug36941.phpt
Modified files: /php-src NEWS /php-src/ext/spl spl_array.c Log: - MFH . Fixed bug #36941 (ArrayIterator does not clone itself) . Fixed SEGV when ArrayObject/Iterator use reference to self . Added tests http://cvs.php.net/viewcvs.cgi/php-src/NEWS?r1=1.2027.2.490&r2=1.2027.2.491&diff_format=u Index: php-src/NEWS diff -u php-src/NEWS:1.2027.2.490 php-src/NEWS:1.2027.2.491 --- php-src/NEWS:1.2027.2.490 Thu Mar 30 19:19:20 2006 +++ php-src/NEWS Tue Apr 4 19:53:21 2006 @@ -13,6 +13,7 @@ - Removed the E_STRICT deprecation notice from "var". (Ilia) - Fixed debug_zval_dump() to support private and protected members. (Dmitry) - Fixed SoapFault::getMessage(). (Dmitry) +- Fixed bug #36941 (ArrayIterator does not clone itself). (Marcus) - Fixed bug #36898 (__set() leaks in classes extending internal ones). (Tony, Dmitry) - Fixed bug #36886 (User filters can leak buckets in some situations). (Ilia) http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/spl_array.c?r1=1.71.2.15&r2=1.71.2.16&diff_format=u Index: php-src/ext/spl/spl_array.c diff -u php-src/ext/spl/spl_array.c:1.71.2.15 php-src/ext/spl/spl_array.c:1.71.2.16 --- php-src/ext/spl/spl_array.c:1.71.2.15 Sat Apr 1 19:13:04 2006 +++ php-src/ext/spl/spl_array.c Tue Apr 4 19:53:21 2006 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: spl_array.c,v 1.71.2.15 2006/04/01 19:13:04 tony2001 Exp $ */ +/* $Id: spl_array.c,v 1.71.2.16 2006/04/04 19:53:21 helly Exp $ */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -67,7 +67,9 @@ } spl_array_object; static inline HashTable *spl_array_get_hash_table(spl_array_object* intern, int check_std_props TSRMLS_DC) { - if ((intern->ar_flags & SPL_ARRAY_USE_OTHER) && (check_std_props == 0 || (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST) == 0)) { + if ((intern->ar_flags & SPL_ARRAY_IS_SELF) != 0) { + return intern->std.properties; + } else if ((intern->ar_flags & SPL_ARRAY_USE_OTHER) && (check_std_props == 0 || (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST) == 0)) { spl_array_object *other = (spl_array_object*)zend_object_store_get_object(intern->array TSRMLS_CC); return spl_array_get_hash_table(other, check_std_props TSRMLS_CC); } else if ((intern->ar_flags & ((check_std_props ? SPL_ARRAY_STD_PROP_LIST : 0) | SPL_ARRAY_IS_SELF)) != 0) { @@ -112,8 +114,10 @@ } /* }}} */ +zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC); + /* {{{ spl_array_object_new */ -static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, spl_array_object **obj, zval *orig TSRMLS_DC) +static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, spl_array_object **obj, zval *orig, int clone_orig TSRMLS_DC) { zend_object_value retval; spl_array_object *intern; @@ -130,13 +134,26 @@ zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); intern->ar_flags = 0; + intern->ce_get_iterator = spl_ce_ArrayIterator; if (orig) { spl_array_object *other = (spl_array_object*)zend_object_store_get_object(orig TSRMLS_CC); - intern->array = orig; - ZVAL_ADDREF(intern->array); intern->ar_flags &= ~ SPL_ARRAY_CLONE_MASK; - intern->ar_flags |= (other->ar_flags & SPL_ARRAY_CLONE_MASK) | SPL_ARRAY_IS_REF | SPL_ARRAY_USE_OTHER; + intern->ar_flags |= (other->ar_flags & SPL_ARRAY_CLONE_MASK); + intern->ce_get_iterator = other->ce_get_iterator; + if (clone_orig) { + intern->array = other->array; + if (Z_OBJ_HT_P(orig) == &spl_handler_ArrayObject) { + ZVAL_ADDREF(intern->array); + SEPARATE_ZVAL(&intern->array); + ZVAL_ADDREF(other->array); + ZVAL_ADDREF(intern->array); + } + } else { + intern->array = orig; + ZVAL_ADDREF(intern->array); + intern->ar_flags |= SPL_ARRAY_IS_REF | SPL_ARRAY_USE_OTHER; + } } else { MAKE_STD_ZVAL(intern->array); array_init(intern->array); @@ -145,7 +162,7 @@ retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_array_object_free_storage, NULL TSRMLS_CC); while (parent) { - if (parent == spl_ce_ArrayIterator) { + if (parent == spl_ce_ArrayIterator || parent == spl_ce_RecursiveArrayIterator) { retval.handlers = &spl_handler_ArrayIterator; break; } else if (parent == spl_ce_ArrayObject) { @@ -156,7 +173,7 @@ inherited = 1; } if (!parent) { /* this must never happen */ - php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of ArrayObject or arrayIterator"); + php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of ArrayObject or ArrayIterator"); } if (inherited) { zend_hash_find(&class_type->function_table, "offsetget", sizeof("offsetget"), (void **) &intern->fptr_offset_get); @@ -186,7 +203,7 @@ static zend_object_value spl_array_object_new(zend_class_entry *class_type TSRMLS_DC) { spl_array_object *tmp; - return spl_array_object_new_ex(class_type, &tmp, NULL TSRMLS_CC); + return spl_array_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC); } /* }}} */ @@ -200,7 +217,7 @@ spl_array_object *intern; old_object = zend_objects_get_address(zobject TSRMLS_CC); - new_obj_val = spl_array_object_new_ex(old_object->ce, &intern, zobject TSRMLS_CC); + new_obj_val = spl_array_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC); new_object = &intern->std; zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC); @@ -828,6 +845,7 @@ } if (object == array) { intern->ar_flags |= SPL_ARRAY_IS_SELF; + intern->ar_flags &= ~SPL_ARRAY_USE_OTHER; } else { intern->ar_flags &= ~SPL_ARRAY_IS_SELF; } @@ -966,7 +984,7 @@ } return_value->type = IS_OBJECT; - return_value->value.obj = spl_array_object_new_ex(intern->ce_get_iterator, &iterator, object TSRMLS_CC); + return_value->value.obj = spl_array_object_new_ex(intern->ce_get_iterator, &iterator, object, 0 TSRMLS_CC); return_value->refcount = 1; return_value->is_ref = 1; } http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/tests/array_022.phpt?view=markup&rev=1.1 Index: php-src/ext/spl/tests/array_022.phpt +++ php-src/ext/spl/tests/array_022.phpt --TEST-- SPL: ArrayObject/Iterator and reference to self --FILE-- ==ArrayObject=== <?php class MyArrayObject extends ArrayObject { public function __construct() { parent::__construct($this); $this['bar'] = 'baz'; } } $a = new MyArrayObject; $b = clone $a; $b['baz'] = 'Foo'; var_dump($a); var_dump($b); ?> ==ArrayIterator=== <?php class MyArrayIterator extends ArrayIterator { public function __construct() { parent::__construct($this); $this['bar'] = 'baz'; } } $a = new MyArrayIterator; $b = clone $a; $b['baz'] = 'Foo'; var_dump($a); var_dump($b); ?> ===DONE=== --EXPECTF-- ==ArrayObject=== object(MyArrayObject)#%d (1) { ["bar"]=> string(3) "baz" } object(MyArrayObject)#%d (2) { ["bar"]=> string(3) "baz" ["baz"]=> string(3) "Foo" } ==ArrayIterator=== object(MyArrayIterator)#%d (1) { ["bar"]=> string(3) "baz" } object(MyArrayIterator)#%d (2) { ["bar"]=> string(3) "baz" ["baz"]=> string(3) "Foo" } ===DONE=== --UEXPECTF-- ==ArrayObject=== object(MyArrayObject)#%d (1) { [u"bar"]=> unicode(3) "baz" } object(MyArrayObject)#%d (2) { [u"bar"]=> unicode(3) "baz" [u"baz"]=> unicode(3) "Foo" } ==ArrayIterator=== object(MyArrayIterator)#%d (1) { [u"bar"]=> unicode(3) "baz" } object(MyArrayIterator)#%d (2) { [u"bar"]=> unicode(3) "baz" [u"baz"]=> unicode(3) "Foo" } ===DONE=== http://cvs.php.net/viewcvs.cgi/php-src/ext/spl/tests/bug36941.phpt?view=markup&rev=1.1 Index: php-src/ext/spl/tests/bug36941.phpt +++ php-src/ext/spl/tests/bug36941.phpt --TEST-- Bug #36941 (ArrayIterator does not clone itself) --FILE-- <?php $a = new ArrayIterator(); $a[] = 1; $b = clone $a; var_dump($a[0], $b[0]); $b[0] = $b[0] + 1; var_dump($a[0], $b[0]); $b[0] = 3; var_dump($a[0], $b[0]); ?> ===DONE=== --EXPECT-- int(1) int(1) int(1) int(2) int(1) int(3) ===DONE=== -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php