php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #6417 Incorrect behaviour with references and arrays
Submitted: 2000-08-29 12:17 UTC Modified: 2002-08-22 11:18 UTC
Votes:3
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:0 (0.0%)
From: jon at imagenet dot co dot uk Assigned:
Status: Closed Package: Scripting Engine problem
PHP Version: 4.0.6-dev OS: Linux RedHat 6.2
Private report: No CVE-ID: None
 [2000-08-29 12:17 UTC] jon at imagenet dot co dot uk
<?php
/*
	I've discovered some slightly counter-intuitive behaviour
	with references and arrays. I'm not sure whether this is
	actually a bug or a 'feature', but if it is the latter then
	it should be documented as such.

	Consider the following code involving references and integers:
 */

$a = 5;
$b = &$a;
$c = $a;
$c = 10;

echo "(1) a: $a (should be 5)<br>\n";

/*
 	Here we have created a variable ($a), made a reference to it ($b),
	made a copy of the original variable ($c), changed the copy ($c=10),
	and then printed out the original value.
	
	This is all fine and as expected.

	Now let's try the same thing, but with the addition of arrays:
 */

$A = array();
$A[0] = 5;
$b = &$A[0];
$C = $A;
$C[0] = 10;

echo "(2) A[0]: $A[0] (I expected it to be 5)<br>\n";

/*
	Thus, having copied the array $A to $C, we have actually made
	$C[0] *another* reference to the $A[0] (which is also referenced
	by $c). I would have expected $C[0] to have become detached from
	the reference (as in $c = $a in the first example).
	
	Taking out the line '$b = &$A[0]' in the example above yields the
	expected behaviour:
 */

$A = array();
$A[0] = 5;
$C = $A;
$C[0] = 10;

echo "(3) A[0]: $A[0] (expected it to actually be 5 this time)<br>\n";

/*
	Q: What's the explanation for all of this?
	
	A: When the Zend Engine constructs a copy of an array/hash, it constructs
	copies of the individual elements by using zval_add_ref (zend_variables.c).
	This simply increases the reference count of the value in question. If
	that value happens to be referenced by more than one name, it has
	the 'is_ref' flag set. However, in the case of copying array elements,
	the values are still _not_ separated if they have 'is_ref' set.
	
	As I mentioned above, I'm not sure whether this is actually the desired
	behaviour or not. In either case, I couldn't find it documented clearly
	anywhere (maybe I didn't look hard enough--if not, sorry in advance!).
	
	Working under the assumption that the behaviour is incorrect (I 
	certainly find it very confusing), I worked out the following fix to
	the issue (assuming my understanding of the Zend Engine is correct):
	
		Instead of using zval_add_ref as the constructor when copying arrays,
		use this:
		
		ZEND_API void zval_add_ref_or_separate(zval **p)
		{
			if (PZVAL_IS_REF(*p))
			{
				SEPARATE_ZVAL(p);
			} else {
				zval_add_ref(p);
			}
		}
	
	Another question is whether there are similar issues with objects? I 
	haven't investigated...

	Note: I haven't included PHP modules/php.ini etc since I'm
fairly sure
	this issue is unrelated to any site-specific setup.
 */	
?>

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2001-05-23 18:49 UTC] jeroen@php.net
Resurfacing.

Is there any work being done on this? Or should I put this in the docs? 

If you don't expect it, this bug can create very strange behaviour, for example when you have some library function that creates references, it can mix up your script.

This is definitely a bug, and should be fixed a.s.a.p.
The fix is included here!

status -> analyzed (imo it is even critical, this is straight against the principle of assigning by value:

[documentation]
>In PHP, variables are always assigned by value. That is to
>say, when you assign an expression to a variable, the
>entire value of the original expression is copied into the
>destination variable. This means, for instance, that after
>assigning one variable's value to another, changing one of
>those variables will have no effect on the other.

)
 [2001-11-22 18:24 UTC] venaas@php.net
I would like to see this fixed, it's a serious bug IMO.
Hope this serves as a reminder to someone (:


 [2001-12-12 08:12 UTC] yohgaki@php.net
I think PHP version (and OS) is better to be updated. It's hard to know which version is the last PHP version tested.
 [2002-02-11 03:18 UTC] nassar at wpi dot edu
See bug number 11909 for a similar issue related to objects
 [2002-06-24 23:43 UTC] pkeshish at idontlike dot spam dot yahoo dot com
Confirmed on PHP Version 4.2.1
 [2002-08-22 11:18 UTC] iliaa@php.net
This bug has been fixed in CVS.

In case this was a PHP problem, snapshots of the sources are packaged
every three hours; this change will be in the next snapshot. You can
grab the snapshot at http://snaps.php.net/.
 
In case this was a documentation problem, the fix will show up soon at
http://www.php.net/manual/.

In case this was a PHP.net website problem, the change will show
up on the PHP.net site and on the mirror sites in short time.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Fri Oct 18 21:01:27 2019 UTC