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