diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 3d9d2a9535cbd..b47e96f60881e 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -44,8 +44,6 @@ typedef struct _spl_array_object { uint32_t ht_iter; int ar_flags; unsigned char nApplyCount; - bool is_child; - Bucket *bucket; zend_function *fptr_offset_get; zend_function *fptr_offset_set; zend_function *fptr_offset_has; @@ -166,8 +164,6 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zend_o object_properties_init(&intern->std, class_type); intern->ar_flags = 0; - intern->is_child = false; - intern->bucket = NULL; intern->ce_get_iterator = spl_ce_ArrayIterator; if (orig) { spl_array_object *other = spl_array_from_obj(orig); @@ -464,22 +460,6 @@ static zval *spl_array_read_dimension(zend_object *object, zval *offset, int typ return spl_array_read_dimension_ex(1, object, offset, type, rv); } /* }}} */ -/* - * The assertion(HT_ASSERT_RC1(ht)) failed because the refcount was increased manually when intern->is_child is true. - * We have to set the refcount to 1 to make assertion success and restore the refcount to the original value after - * modifying the array when intern->is_child is true. - */ -static uint32_t spl_array_set_refcount(bool is_child, HashTable *ht, uint32_t refcount) /* {{{ */ -{ - uint32_t old_refcount = 0; - if (is_child) { - old_refcount = GC_REFCOUNT(ht); - GC_SET_REFCOUNT(ht, refcount); - } - - return old_refcount; -} /* }}} */ - static void spl_array_write_dimension_ex(int check_inherited, zend_object *object, zval *offset, zval *value) /* {{{ */ { spl_array_object *intern = spl_array_from_obj(object); @@ -503,19 +483,12 @@ static void spl_array_write_dimension_ex(int check_inherited, zend_object *objec } Z_TRY_ADDREF_P(value); - - uint32_t refcount = 0; if (!offset || Z_TYPE_P(offset) == IS_NULL) { ht = spl_array_get_hash_table(intern); if (UNEXPECTED(ht == intern->sentinel_array)) { return; } - refcount = spl_array_set_refcount(intern->is_child, ht, 1); zend_hash_next_index_insert(ht, value); - - if (refcount) { - spl_array_set_refcount(intern->is_child, ht, refcount); - } return; } @@ -530,17 +503,13 @@ static void spl_array_write_dimension_ex(int check_inherited, zend_object *objec spl_hash_key_release(&key); return; } - refcount = spl_array_set_refcount(intern->is_child, ht, 1); + if (key.key) { zend_hash_update_ind(ht, key.key, value); spl_hash_key_release(&key); } else { zend_hash_index_update(ht, key.h, value); } - - if (refcount) { - spl_array_set_refcount(intern->is_child, ht, refcount); - } } /* }}} */ static void spl_array_write_dimension(zend_object *object, zval *offset, zval *value) /* {{{ */ @@ -570,8 +539,6 @@ static void spl_array_unset_dimension_ex(int check_inherited, zend_object *objec } ht = spl_array_get_hash_table(intern); - uint32_t refcount = spl_array_set_refcount(intern->is_child, ht, 1); - if (key.key) { zval *data = zend_hash_find(ht, key.key); if (data) { @@ -596,10 +563,6 @@ static void spl_array_unset_dimension_ex(int check_inherited, zend_object *objec } else { zend_hash_index_del(ht, key.h); } - - if (refcount) { - spl_array_set_refcount(intern->is_child, ht, refcount); - } } /* }}} */ static void spl_array_unset_dimension(zend_object *object, zval *offset) /* {{{ */ @@ -973,15 +936,6 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar } else { //??? TODO: try to avoid array duplication ZVAL_ARR(&intern->array, zend_array_dup(Z_ARR_P(array))); - - if (intern->is_child) { - Z_TRY_DELREF(intern->bucket->val); - /* - * replace bucket->val with copied array, so the changes between - * parent and child object can affect each other. - */ - ZVAL_COPY(&intern->bucket->val, &intern->array); - } } } else { if (Z_OBJ_HT_P(array) == &spl_handler_ArrayObject) { @@ -1244,7 +1198,7 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, size_t f *ht_ptr = Z_ARRVAL_P(ht_zv); ZVAL_NULL(ht_zv); zval_ptr_dtor(¶ms[0]); - zend_string_free(Z_STR(function_name)); + zval_ptr_dtor(&function_name); } } /* }}} */ @@ -1854,15 +1808,6 @@ PHP_METHOD(RecursiveArrayIterator, hasChildren) static void spl_instantiate_child_arg(zend_class_entry *pce, zval *retval, zval *arg1, zval *arg2) /* {{{ */ { object_init_ex(retval, pce); - spl_array_object *new_intern = Z_SPLARRAY_P(retval); - /* - * set new_intern->is_child is true to indicate that the object was created by - * RecursiveArrayIterator::getChildren() method. - */ - new_intern->is_child = true; - - /* find the bucket of parent object. */ - new_intern->bucket = (Bucket *)((char *)(arg1) - XtOffsetOf(Bucket, val));; zend_call_known_instance_method_with_2_params(pce->constructor, Z_OBJ_P(retval), NULL, arg1, arg2); } /* }}} */ diff --git a/ext/spl/tests/bug42654.phpt b/ext/spl/tests/bug42654.phpt index eb72863e08759..20aad74b73423 100644 --- a/ext/spl/tests/bug42654.phpt +++ b/ext/spl/tests/bug42654.phpt @@ -110,11 +110,11 @@ object(RecursiveArrayIterator)#%d (1) { [2]=> array(2) { [2]=> - string(5) "alter" + string(4) "val2" [3]=> array(1) { [3]=> - string(5) "alter" + string(4) "val3" } } [4]=> @@ -129,11 +129,11 @@ object(RecursiveArrayIterator)#%d (1) { [2]=> array(2) { [2]=> - string(5) "alter" + string(4) "val2" [3]=> array(1) { [3]=> - string(5) "alter" + string(4) "val3" } } [4]=> @@ -146,11 +146,11 @@ array(3) { [2]=> array(2) { [2]=> - string(5) "alter" + string(4) "val2" [3]=> array(1) { [3]=> - string(5) "alter" + string(4) "val3" } } [4]=> diff --git a/ext/spl/tests/bug42654_2.phpt b/ext/spl/tests/bug42654_2.phpt deleted file mode 100644 index bd290247dbdc4..0000000000000 --- a/ext/spl/tests/bug42654_2.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---TEST-- -Bug #42654 (RecursiveIteratorIterator modifies only part of leaves) ---FILE-- - 'val1', array('key2' => 'val2'), 'key3' => 'val3'); - -$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($data)); -foreach($iterator as $foo) { - $key = $iterator->key(); - switch($key) { - case 'key1': // first level - case 'key2': // recursive level - echo "update $key".PHP_EOL; - $iterator->offsetSet($key, 'alter'); - } -} -$copy = $iterator->getArrayCopy(); -var_dump($copy); -?> ---EXPECT-- -update key1 -update key2 -array(3) { - ["key1"]=> - string(5) "alter" - [0]=> - array(1) { - ["key2"]=> - string(5) "alter" - } - ["key3"]=> - string(4) "val3" -} diff --git a/ext/spl/tests/gh10519.phpt b/ext/spl/tests/gh10519.phpt index 1f7572d6e8ca6..87e7eae0cf0c8 100644 --- a/ext/spl/tests/gh10519.phpt +++ b/ext/spl/tests/gh10519.phpt @@ -1,5 +1,7 @@ --TEST-- Bug GH-10519 (Array Data Address Reference Issue) +--XFAIL-- +The fix for this was bad --FILE-- getChildren(); +unset($it); +$child->__construct([2, 3]); +var_dump($child->getArrayCopy()); +?> +--EXPECT-- +array(2) { + [0]=> + int(2) + [1]=> + int(3) +}