php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #53863 scalar reference of array element has unintended side effects
Submitted: 2011-01-28 07:45 UTC Modified: 2014-11-18 21:15 UTC
Votes:4
Avg. Score:3.8 ± 0.4
Reproduced:4 of 4 (100.0%)
Same Version:1 (25.0%)
Same OS:2 (50.0%)
From: elrah at polyptych dot com Assigned:
Status: Not a bug Package: Variables related
PHP Version: 5.3.5 OS: CentOS 5.5
Private report: No CVE-ID: None
 [2011-01-28 07:45 UTC] elrah at polyptych dot com
Description:
------------
Adding a scalar reference to an array element changes array assignment behavior.   
In a regular array assignment, elements are all copied by value.  But if a scalar 
reference has been made to an array element, that element is copied by reference 
in a subsequent array assignment.  The code looks exactly the same, so the 
behavior shouldn't change just because there's a reference floating out there 
somewhere.

Test script:
---------------
<?php
$arr1 = array(1);
echo "\nbefore:\n";
echo "\$arr1[0] == {$arr1[0]}\n";
$arr2 = $arr1;
$arr2[0]++;
echo "\nafter:\n";
echo "\$arr1[0] == {$arr1[0]}\n";
echo "\$arr2[0] == {$arr2[0]}\n";
$arr3 = array(1);
$a =& $arr3[0];
echo "\nbefore:\n";
echo "\$a == $a\n";
echo "\$arr3[0] == {$arr3[0]}\n";
$arr4 = $arr3;
$arr4[0]++;
echo "\nafter:\n";
echo "\$a == $a\n";
echo "\$arr3[0] == {$arr3[0]}\n";
echo "\$arr4[0] == {$arr4[0]}\n";

Expected result:
----------------
before:
$arr1[0] == 1

after:
$arr1[0] == 1
$arr2[0] == 2

before:
$a == 1
$arr3[0] == 1

after:
$a == 1
$arr3[0] == 1
$arr4[0] == 2


Actual result:
--------------
before:
$arr1[0] == 1

after:
$arr1[0] == 1
$arr2[0] == 2

before:
$a == 1
$arr3[0] == 1

after:
$a == 2
$arr3[0] == 2
$arr4[0] == 2


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-11-18 20:07 UTC] sohagan at gmail dot com
In PHP 5.3.3 (on Linux 2.6.32-431.23.3.el6.x86_64), there is a related(identical?) bug which causes the last element of an array to be passed/assigned by reference if its parent array is used as a reference. 

For example, foreach ($my_array as &$array_val) {...} will cause the last element of $my_array to be assigned by reference: 

    $my_new_array = $my_array; 
    $my_new_array[4] = null; // if $my_array's last index is 4, this will nullify that value too 

and passed by reference: 

    function dont_touch($param) { // modify $param here } 
    dont_touch($my_array[4]); // $my_array[4] will be modified 

This can be fixed by unsetting the reference to the array value after the foreach loop. 

    unset($array_val); // after the foreach loop

Try running this code and comment/uncomment the line containing "unset". 

<?php 

$thingies = array(array(1,2,3,4),array(1,2,3,4)); 

var_dump($thingies); 

foreach ($thingies as &$things) { 
    foreach ($things as $thing) { 
        $thing += 1; 
    } 
} 

unset($things); 

$copythings = $thingies; 
$copythings[1][0] += 1; 
$copythings[1][1] += 1; 
$copythings[1][2] += 1; 
$copythings[1][3] += 1; 

var_dump($thingies); 

?>
 [2014-11-18 21:15 UTC] rasmus@php.net
-Status: Open +Status: Not a bug
 [2014-11-18 21:15 UTC] rasmus@php.net
There isn't actually a bug here. This is how references work and there is no change of behaviour from one version to the next. All versions of PHP give the same result here.
 [2014-11-19 15:32 UTC] sohagan at gmail dot com
Here's the relevant documention showing that this is expected behaviour:
http://php.net/manual/en/language.references.whatdo.php
(search for "Assignment of array variables")
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Jul 18 02:01:29 2024 UTC