php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #44658 References to references triggers unwanted further references
Submitted: 2008-04-07 11:46 UTC Modified: 2008-04-23 07:45 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: mo at nevali dot net Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 5.2.5 OS: FreeBSD 6
Private report: No CVE-ID: None
 [2008-04-07 11:46 UTC] mo at nevali dot net
Description:
------------
Some circumstances involving deep references into arrays can cause 
assignment of those arrays to always assign references instead of 
values.






Reproduce code:
---------------
Please see http://nevali.net/docs/array-refs-testcase.phps

Expected result:
----------------
The code should produce the following output:

Created foo, foo->thing['stuff'] = 1234
Creating Bar, foo->thing['stuff'] = 1234
Created bar, bar->thing2['stuff'] = ABC
Created bar, foo->thing['stuff'] = 1234






Actual result:
--------------
Created foo, foo->thing['stuff'] = 1234
Creating Bar, foo->thing['stuff'] = 1234
Created bar, bar->thing2['stuff'] = ABC
Created bar, foo->thing['stuff'] = ABC

If the (marked) line in Foo's constructor:

$this->stuff =& $this->thing['stuff'];

?is removed, the output is as expected, even though this code should be 
inert (Foo::stuff is not referenced from anywhere else in the test 
code).


 

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-04-07 12:11 UTC] jani@php.net
This is the expected and correct output:

Created foo, foo->thing['stuff'] = 1234
Creating Bar, foo->thing['stuff'] = 1234
Created bar, bar->thing2['stuff'] = ABC
Created bar, foo->thing['stuff'] = ABC

Hint: References are not pointers.
 [2008-04-07 12:36 UTC] mo at nevali dot net
So, how do you explain the difference in behaviour when the (should-
be-inert) line in Foo::__construct() is removed?

Also, while I'm perfectly well aware that references are not pointers, 
even calling (for example): $this->thing = array_merge($foo->thing, 
array()); in Bar::__construct() causes $bar->thing to become a 
reference.

If this report _is_ bogus, then:

a) Creating a deep reference (i.e., $this->thing2 =& $this-
>thing['stuff']: in Foo::__construct()) should have no bearing on 
anything; $foo->thing2 is not used beyond that initial assignment.

b) How is one supposed to duplicate the contents of an array given a 
reference to it? Last I heard, the use of ?clone? was only supported 
for objects.

Whilst this report may be, on the face of it, bogus, there is a bug 
here in either case.
 [2008-04-07 12:37 UTC] mo at nevali dot net
My apologies, in my previous follow-up, I meant to write ?$foo->stuff? 
where I wrote ?$foo->thing2?. In my testcase, there's no such property 
as $foo->thing2!
 [2008-04-11 08:40 UTC] mo at nevali dot net
If this bug has been marked as bogus, does it mean it's going to get 
summarily ignored from here on in?

It would be nice if somebody could actually try _running_ the test-case 
instead of dismissing it out of hand; aspects of the behaviour are 
clearly incorrect (notably the inconsistency), even if it's the case 
that my summary of it is wrong.
 [2008-04-21 06:23 UTC] jani@php.net
FYI: I did run your (bogus) testcase.
 [2008-04-22 22:36 UTC] mo at nevali dot net
Okay, let me rephrase, because I'm obviously not being clear about 
something or other.

Line 12 of the testcase is the following:

$this->stuff =& $this->thing['stuff'];

If this line is commented out, the output changes (to my ?expected 
result?). If this line is uncommented, the output is as per your 
?expected result?.

Foo::$stuff is not referenced anywhere (beyond its initial 
declaration) except for this line.

Your statement ?references are not pointers? to me, as an experienced 
C programmer, suggests that under no circumstances, except for the 
assignment of object instances, should the following result in $b 
being a reference to $a:

$b = $a;

In the testcase (tested on PHP 5.2.5 with debugging enabled, and PHP 
5.1.6 with debugging enabled, both command-line and Apache 2 Handler 
SAPIs), line 24 behaves as though it were written:

$this->thing2 =& $foo->thing;

?if, and only if, line 12 is uncommented. Otherwise, it behaves as it 
is written:

$this->thing2 = $foo->thing;

There is NO documented reason why this behaviour should occur.

Now, if you _still_ think this is bogus, I'd really appreciate an 
explanation, with appropriate references to the documentation, as to 
why it's bogus, because if it is I'm evidently a simpleton who can't 
read and I'm now becoming slightly frustrated by both this issue and 
the unhelpfully terse responses to it.
 [2008-04-23 07:37 UTC] colder@php.net
colder@jack /var/cvs/php.net/php5.3-dev $ sapi/cli/php -r '$v = 2; $a = array("k" => &$v); $b = $a; $b["k"]++; echo $v;'
3

When arrays get copied, the elements that are references are kept as references.
 [2008-04-23 07:45 UTC] mo at nevali dot net
Thank you!

That makes perfect sense, and explains what jani meant by ?references 
are not pointers?.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat May 18 15:01:33 2024 UTC