php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #39011 foreach($_GET as $key => &$value) causes later bugs passing $_GET as a paramete
Submitted: 2006-10-01 19:25 UTC Modified: 2006-10-02 10:32 UTC
From: php_bug dot email at email dot digiways dot com Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 5.1.6 OS: Windows XP
Private report: No CVE-ID: None
 [2006-10-01 19:25 UTC] php_bug dot email at email dot digiways dot com
Description:
------------
if we iterate over $_GET using references (see the example) and pass $_GET to a function, function modifies $_GET and not the local copy.
For example, save the example code in test.php and open

test.php?mykey=foo
.

Reproduce code:
---------------
<?php
		function doit($http_get_params)
		{
			$http_get_params['mykey'] = 'bar';
			echo '<br/>'.$_GET['mykey'];
		}

		foreach($_GET as $key => &$value) {}

		echo '<br/>'.$_GET['mykey'];
		doit($_GET);
		echo '<br/>'.$_GET['mykey'];
?>


Expected result:
----------------
When we open test.php?mykey=foo I expect to see
foo
foo
foo

Actual result:
--------------
When we open test.php?mykey=foo we actually see
foo
bar
bar

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-10-01 20:13 UTC] sitnikov at infonet dot ee
confirmed with PHP Version 5.2.0RC5-dev
 [2006-10-01 20:24 UTC] judas dot iscariote at gmail dot com
this is the expected behaviuor, and not a bug. :P

the reasons are clearly explained by gardan at gmx dot de on this report, please do a search before reporting

http://bugs.php.net/bug.php?id=29992
 [2006-10-01 20:39 UTC] iliaa@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

bogus
 [2006-10-01 21:00 UTC] php_bug dot email at email dot digiways dot com
Where exactly is this behaviour documented? Can you point to the documentation page as I failed to find this.

Also, another defect http://bugs.php.net/bug.php?id=29992 which was referenced here is a different problem. In my case I do not reuse the reference variable $value .
 [2006-10-01 21:37 UTC] php_bug dot email at email dot digiways dot com
This problem affects all the arrays and not just the $_GET one. Please note that $value is not reused outside of the foreach loop. Effectively this renders foreach by reference useless.

Another very simple script which reproduces the problem:

	$myarray = array( 'mykey' => 'foo' );
	function doit($tmp) { $tmp['mykey'] = 'bar'; }
	foreach($myarray as $key => &$value) {}
	echo $myarray['mykey']."\n";
	doit($myarray);
	echo $myarray['mykey']."\n";

and outputs
   foo
   bar
instead of
   foo
   foo
 [2006-10-01 21:39 UTC] plyrvt at mail dot ru
Confirm with 5.1.6:
<?php
$a['b']='foo';
function boo($_params){
	$_params['b'] = 'bar';
	echo $a['b'];
}

foreach($a as $key => &$val) {} // ?!

	echo $a['b'];
	boo($a);
	echo $a['b'];
?>

If you comment out `foreach` loop or remove & near `$val`, code works OK. Loop does nothing and $val is *never* mentioned in code elsewhere.
 [2006-10-01 21:55 UTC] plyrvt at mail dot ru
If you add unset($val) after foreach, original array starts back to work as expected:

<?php
$a['b']='foo';
function boo($_params){
	$_params['b'] = 'bar';
	echo $_params['b'];
}

foreach($a as $key => &$val) {}
unset($val);

	echo $a['b'];
	boo($a);
	echo $a['b'];
/*
foo
bar
foo
*/
?>
 [2006-10-01 22:02 UTC] php_bug dot email at email dot digiways dot com
Actually this is not just about foreach, this is the generic problem with references.
Apparently if you have a reference to an array element, then when you pass that array to a function and modify that element in the function, then the external array is modified as well, and not just the copy passed to the function.

A small example which shows the problem:
	$myarray = array( 'mykey' => 'foo' );
	function doit($tmp) { $tmp['mykey'] = 'bar'; }
	$value = &$myarray['mykey'];
	echo $myarray['mykey']."\n";
	doit($myarray);
	echo $myarray['mykey']."\n";

Once again - can anyone point to the documentation page which explains this behaviour ?
 [2006-10-01 22:12 UTC] plyrvt at mail dot ru
This bug can be described shortly:
"Existance of a reference to the element of an array prevents this element to be passed by value as long as any reference point to it"
 [2006-10-01 22:34 UTC] judas dot iscariote at gmail dot com
again, THIS IS NOT A BUG ?!

but yes,this behaviuor should be described in the documentation I think.

I still think this kind of code should raise an E_WARNING or something ( the idea was proposed a while ago, but refused)
 [2006-10-01 22:42 UTC] php_bug dot email at email dot digiways dot com
Documentation describes that parameters are passed to functions by value by default. And since the behaviour you are talking about is not documented anywhere, it is definitely a bug.

So, I suggest you read PHP documentation starting with
http://www.php.net/manual/en/functions.arguments.php
which clearly states:
===
By default, function arguments are passed by value (so that if you change the value of the argument within the function, it does not get changed outside of the function). If you wish to allow a function to modify its arguments, you must pass them by reference.
===

and then explain it again why the problem described above is not a bug although it does not do what PHP documentation states it does.
 [2006-10-02 08:46 UTC] tony2001@php.net
>Documentation describes that parameters are passed to >functions by value by default. 
They are passed by value, including all the references in the array. And since all the elements in the array are references, you're able to modify them in the function.
See var_dump($myarray);
 [2006-10-02 10:09 UTC] php_bug dot email at email dot digiways dot com
> And since all the elements in the array are references

Are you talking about arrays in general, or about my example?

If you are talking about arrays in general, this is simply wrong, a simple example can demostrate that.

If you are talking about my example, then please explain why the element in the array becomes a reference if we add a reference to it?

I.e.
   $a = array('foo' => 'bar');
here $a contains the value 'bar' and not the reference to it.
   $tmp = &$a['foo'];
Are you saying that now $a has changed and now it contains a reference to 'bar' and does not contain it as a value any more? Where is this documented?
 [2006-10-02 10:32 UTC] tony2001@php.net
>Are you talking about arrays in general, or about my example?

I'm talking about your example, of course.

>If you are talking about my example, then please explain >why the element in the array becomes a reference if we add >a reference to it?

Because they both now point to the same value. This is how references work.
See what the docs say: http://www.php.net/manual/en/language.references.whatdo.php
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu May 02 19:01:29 2024 UTC