ID: 42316
User updated by: titerm at lfdj dot com
-Summary: RecursiveArrayIterator mix refcount and reference :
Bad reproduce code
Reported By: titerm at lfdj dot com
-Status: Feedback
+Status: Open
Bug Type: SPL related
Operating System: Windows
PHP Version: 5.2.3
New Comment:
Create a ArrayIterator on branch1. Alter the leaf by using iterator.
Leave on branch2 are affected too.
Simplified reproduce code.
$data['one'] = 'ORG';
$arr = array (
'branch1' => $data,
'branch2' => $data,
);
$iterator = new ArrayIterator($arr['branch1']);;
$iterator->offSetSet($iterator->key(), 'ALTER' );
var_dump($arr);
Expected result
array
'branch1' =>
array
'one' => string 'ALTER' (length=5)
'branch2' =>
array
'one' => string 'ORG' (length=3)
Actual result
array
'branch1' =>
array
'one' => string 'ALTER' (length=5)
'branch2' =>
array
'one' => string 'ALTER' (length=5)
Previous Comments:
------------------------------------------------------------------------
[2007-08-16 10:45:42] [EMAIL PROTECTED]
What if you didn't pay attention to the internals like refcount but
only for actual results? Can you come up with a short and simple example
of what actually doesn't work?
------------------------------------------------------------------------
[2007-08-16 08:32:05] titerm at lfdj dot com
I have simplified the reproduce code to much. Sorry
it should be
$iterator = new RecursiveIteratorIterator(new
RecursiveArrayIterator($arr['l1']));
foreach($iterator as $leaf) {
$iterator->offSetSet($iterator->key(), 'ALTER' );
}
Expected result
array(3) refcount(2){
["l1"]=>
array(1) refcount(1){
["one"]=>
array(1) refcount(1){
["two"]=>
string(5) "ALTER" refcount(1)
}
}
["l2"]=>
array(1) refcount(1){
["one"]=>
array(1) refcount(1){
["two"]=>
string(3) "ORG" refcount(2)
}
}
["l3"]=>
array(1) refcount(1){
["one"]=>
array(1) refcount(1){
["two"]=>
string(3) "ORG" refcount(1)
}
}
}
Actual Result
array(3) refcount(2){
["l1"]=>
array(1) refcount(3){
["one"]=>
array(1) refcount(1){
["two"]=>
string(5) "ALTER" refcount(1)
}
}
["l2"]=>
array(1) refcount(1){
["one"]=>
array(1) refcount(1){
["two"]=>
string(3) "ORG" refcount(2)
}
}
["l3"]=>
array(1) refcount(3){
["one"]=>
array(1) refcount(1){
["two"]=>
string(5) "ALTER" refcount(1)
}
}
}
------------------------------------------------------------------------
[2007-08-16 08:18:32] titerm at lfdj dot com
Description:
------------
When multiple entries of an array are initialized with a $base var
array, new entries will increase refcount.
Any modification of this new entries should decrease refcount.
But if modification are done through a recursive Array Iterator,
refcount works like it was reference, and all leaf are modified
Reproduce code:
---------------
// Reference var array
$base['one']['two'] = 'ORG';
// Work array
$arr = array (
'l1' => $base,
'l2' => $base,
'l3' => $base,
);
unset($base); // No need anymore of reference
// Break refcount for level 2, level 1 and level 3 are still refcount
$arr['l2']['one']['two'] = $arr['l2']['one']['two'];
// Create an iterator on level 1
$iterator = new RecursiveIteratorIterator(new
RecursiveArrayIterator($arr['l1']));
// Alter leaf of level 1
$iterator->offSetSet($iterator->key(), 'ALTER' );
debug_zval_dump($arr);
Expected result:
----------------
array(3) refcount(2){
["l1"]=>
array(1) refcount(1){
["one"]=>
string(5) "ALTER" refcount(1)
}
["l2"]=>
array(1) refcount(1){
["one"]=>
array(1) refcount(1){
["two"]=>
string(3) "ORG" refcount(1)
}
}
["l3"]=>
array(1) refcount(1){
["one"]=>
string(3) "ORG" refcount(1)
}
}
Actual result:
--------------
array(3) refcount(2){
["l1"]=>
array(1) refcount(3){
["one"]=>
string(5) "ALTER" refcount(1)
}
["l2"]=>
array(1) refcount(1){
["one"]=>
array(1) refcount(1){
["two"]=>
string(3) "ORG" refcount(1)
}
}
["l3"]=>
array(1) refcount(3){
["one"]=>
string(5) "ALTER" refcount(1)
}
}
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=42316&edit=1