ID:               48646
 Comment by:       phpwnd at gmail dot com
 Reported By:      php at mrfoo dot de
 Status:           Open
 Bug Type:         SimpleXML related
 Operating System: Windows XP / Debian Lenny
 PHP Version:      5.2.10
 New Comment:

Verified on 5.3CVS-2009-06-23 too.


Previous Comments:
------------------------------------------------------------------------

[2009-06-22 22:23:49] phpwnd at gmail dot com

I have investigated this bug a little bit (on 5.2.9), and it seems that
some pointer gets reset to the first node of the list whenever the value
of any node from the list is modified, which makes the next iteration
apply to the second node of the list, where it gets stuck forever. In my
case, modifying a descendant of those nodes (as opposed to the nodes
themselves) did NOT reset the pointer, but I assume it's the same bug.

Here's a reduced test case, which gets stuck on <c>1</c>:


$xml = simplexml_load_string('<root><c>0</c><c>1</c><c>2</c></root>');

$i = -1;
foreach ($xml as $child)
{
        if (++$i > 3)
        {
                die('Too many iterations');
        }

        echo 'Current node: ', $child->asXML(), "\n\nBefore: ", $xml->asXML(),
"\n";
        $xml->c[2] = "changed: $i";
        echo 'After: ', $xml->asXML(), "\n\n";
}

------------------------------------------------------------------------

[2009-06-22 15:13:21] php at mrfoo dot de

I forget to say: Tested with 5.2.10(win) too.

------------------------------------------------------------------------

[2009-06-22 15:00:26] php at mrfoo dot de

Description:
------------
Tested with: 5.2.6(win), 5.2.9(win) and 5.2.9-0.dotdeb.2 (lin).

Writing a value of a SimpleXML-Element in a foreach loop, causes PHP to
never leave the foreach loop, if you access that element via an extra
index.


Reproduce code:
---------------
error_reporting(E_ALL);
$xmlData = '<root><child><name>A
child</name><info><version>1</version></info></child><child><name>B
child</name><info><version>2</version></info></child><child><name>C
child</name><info><version>2</version></info></child><child><name>D
child</name><info><version>3</version></info></child></root>';
$xml = simplexml_load_string($xmlData);
$i = -1;
foreach ($xml as $xi => $child) {
    ++$i;
    $xml->child[$i]->info->version = rand(1,9);
    echo 'I: '.$i.' Xi: '.$xi.' Count : '.count($xml).'
'.$xml->child[$i]->name.' => '.$child->name.'
v:'.$child->info->version."\n";
    if($i > 10) {
        echo "Too many iterations";
        break;
    }
}
// Code below works as expected
$xml = simplexml_load_string($xmlData);
for($i = 0, $size = count($xml); $i < $size; ++$i) {
    echo 'I: '.$i.' Count : '.count($xml).'
'.$xml->child[$i]->name."\n";
    $xml->child[$i]->info->version = rand(1,9);
}

Expected result:
----------------
Something like that:

I: 0 Xi: child Count : 4 A child => A child v:1
I: 1 Xi: child Count : 4 B child => B child v:3
I: 2 Xi: child Count : 4 C child => C child v:3
I: 3 Xi: child Count : 4 D child => D child v:7
I: 0 Count : 4 A child
I: 1 Count : 4 B child
I: 2 Count : 4 C child
I: 3 Count : 4 D child


Actual result:
--------------
I: 1 Xi: child Count : 4 B child => B child v:6
I: 2 Xi: child Count : 4 C child => B child v:6
I: 3 Xi: child Count : 4 D child => B child v:6
I: 4 Xi: child Count : 5  => B child v:6
I: 5 Xi: child Count : 6  => B child v:6
I: 6 Xi: child Count : 7  => B child v:6
I: 7 Xi: child Count : 8  => B child v:6
I: 8 Xi: child Count : 9  => B child v:6
I: 9 Xi: child Count : 10  => B child v:6
I: 10 Xi: child Count : 11  => B child v:6
I: 11 Xi: child Count : 12  => B child v:6
Too many iterations
I: 0 Count : 4 A child
I: 1 Count : 4 B child
I: 2 Count : 4 C child
I: 3 Count : 4 D child



------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=48646&edit=1

Reply via email to