|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2009-06-22 15:00 UTC] 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
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Oct 29 18:00:01 2025 UTC |
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"; }