php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #42236 unwanted array reset within recursive call
Submitted: 2007-08-07 17:21 UTC Modified: 2007-08-16 14:00 UTC
From: remy215 at laposte dot net Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 5.2CVS-2007-08-12 OS: debian
Private report: No CVE-ID: None
 [2007-08-07 17:21 UTC] remy215 at laposte dot net
Description:
------------
I have an array of nested arrays (ie. each id can have nested children). The function returns the parent of the provided id but end in an infinite loop when the id does not exists !
Parent array at the top of the hierarchy seems to undergo an unwanted reset();


Reproduce code:
---------------
<?php
$array=array('a0'=>array('a1'=>array('a2'=>array(),'b2'=>array()),'b1'=>array()),'b0'=>array());
$searched=array(); // to avoid infinite loop
function getParent($id,$_subtree=null) {
	if(!$_subtree) { // if first call
		global $array;
		$_subtree=$array; // entire tree
	}
	global $searched; // to avoid infinite loop
	$found_parent=null;
	foreach($_subtree as $parent=>$children) {
		if(in_array($parent,$searched)) { // if already looped => stop (ie. infinite loop)
			die('Infinite loop: '.$parent);
		}
		array_push($searched,$parent); // to avoid infinite loop
		if(in_array($id,array_keys($children))) {
			$found_parent=$parent;
			break;
		} elseif($found_parent=getParent($id,$children)) {
			break;
		}
	}
	return $found_parent;
}
$search='a0';
echo 'parent of '.$search.' is: '.getParent($search);
?>

Expected result:
----------------
When you provide as argument a nested id, the function works ('b2' returns 'a1').
When you provide a non-existing id, or one of the top parent ids ('a0' or 'b0') the function should return null.

Actual result:
--------------
When you provide a non-existing id, or one of the top parent ids ('a0' or 'b0') the function end up in an infinite loop.
Parent array at the top of the hierarchy seems to undergo an unwanted reset();


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-08-12 21:36 UTC] remy215 at laposte dot net
I tested with latest cvs snapshot, still unexpectingly reseting the array, leading to an unpredictable infinite loop.
 [2007-08-15 08:44 UTC] jani@php.net
Please provide the simplest possible script that shows exactly what is going wrong. The current example is too complex and seems to contain all kinds of useless workarounds..
 [2007-08-15 12:47 UTC] remy215 at laposte dot net
Hi Jani,
First thank you for your support.
Here is a cleaner version (without the infinite-loop checking):
<?php
$array=array(
	'a0'=>array(
		'a1'=>array(
			'a2'=>array(),
			'b2'=>array()
		),'b1'=>array()
	),'b0'=>array()
);

function getParent($id,$_subtree=null) {
	$found_parent=null;
	if(!$_subtree) {
		global $array;
		$_subtree=$array;
	}
	foreach($_subtree as $parent=>$children) {
		if(in_array($id,array_keys($children))) {
			$found_parent=$parent;
			break;
		} elseif($found_parent=getParent($id,$children)) {
			break;
		}
	}
	return $found_parent;
}
echo "\nparent of b2 is: ".getParent('b2'); // expected result: 'a1' -- actual result: 'a1'
echo "\nparent of a0 is: ".getParent('a0'); // expected result: null -- actual result: infinite loop
?>

What's really strange is that if you call getParent('a0',$array), it works perfectly ! it's the [global $array; $_subtree=$array;] used for initialization that triggers an infinite loop.

Regards,
Remy
 [2007-08-15 15:46 UTC] jani@php.net
Try replace the foreach() calls with while/each struct...foreach() does a reset on the array..
 [2007-08-15 23:31 UTC] remy215 at laposte dot net
I know that foreach reset the array.
In fact I am not looking for a workaround, I already have one.
It's just that the behavior of php looks quite unexpected to me and it could be a bug.

Normally, calling << getParent('a0'); >> or calling << getParent('a0',$array); >> should lead exactly to the same result since  when the second argument is not provided, it defaults to $array.
But that's not the case, the first call leads to an infinite loop while the second delivers the expected result (null).

I hope I am not wrong. In any case, thanks for your help.
Regards,
Remy
 [2007-08-16 11:19 UTC] jani@php.net
Now I just want one thing cleared: Did you experience this with earlier PHP versions than 5.2.3? As I'm quite sure it has been like this always. And using global when not really necessary is always bad..
 [2007-08-16 12:54 UTC] remy215 at laposte dot net
I've experienced it 5.2.0 too so far.
Regarding the use of 'global': in fact this function was a method of a class and the global variable was not 'global' but a property of that same class.
I removed all this class wrapper just for this post => this is why I used 'global' to simulate the corresponding class property.

In any case, no worries at all since I've a workaround.
Regards,
remy
 [2007-08-16 14:00 UTC] jani@php.net
Apparently it isn't a workaround but how it's supposed to be done.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Mon Jan 20 23:01:25 2020 UTC