php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72173 very strange reference behavior (bug?) in PHP 5.6, 7.0
Submitted: 2016-05-07 14:16 UTC Modified: 2016-05-07 23:50 UTC
From: cf0hay at gmail dot com Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 7.0.6 OS: Linux 64bit
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: cf0hay at gmail dot com
New email:
PHP Version: OS:

 

 [2016-05-07 14:16 UTC] cf0hay at gmail dot com
Description:
------------
Affects both PHP 5.6.21 and PHP 7.0.6 .

- Create an array with some elements
- Iterate over this array by reference
- assign (copy) this array by value to a different variable
- Iterate over the previous array by reference again using the same variable
- the copied array changes at the value which was the last of the original one


Test script:
---------------
<?php
    $x = [1,2,3];
    foreach($x as &$ref){
        $ref += 100;
    }

    /* $x === [101, 102, 103]
    at this point, $ref is bound to the last element of $x, that's OK */

    $b = $x;
    /* this should logically copy $x to $b *by value* (COW happens) */

    $b[0] = 0; /* this should force an array copy in memory */

    /* here, $ref should be rebound to the elements of $x by reference */
    foreach($x as &$ref){
        $ref += 100;
    }

    /* at this point, $x === [201, 202, 203] which is correct, $ref refers
    to the last element of $x again, which is OK,
    BUT! As we copied $b by value before, is should stay as is, but the last 
    element of $b changes to 203! */
    var_dump($b);


Expected result:
----------------
array(3) {
  [0]=>
  int(0)
  [1]=>
  int(102)
  [2]=>
  int(103)
}


Actual result:
--------------
array(3) {
  [0]=>
  int(0)
  [1]=>
  int(102)
  [2]=>
  &int(203)
}


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-05-07 14:25 UTC] cf0hay at gmail dot com
I consider this a bug, because with integer references this doesn't happen:

<?php
    $a = 5;
    $ref =& $a; //$ref points to the same value as $a
    $ref += 100; //$ref and $a are both 105 because of this
    $b = $a; //this copies the value 105 to a new place
    $ref += 100; //$ref and $a are 205, but $b remains 105 correctly
    var_dump($b);
 [2016-05-07 14:35 UTC] cf0hay at gmail dot com
Short version of the bug:

<?php
    $orig = [1];
    $ref =& $orig[0];
    $copy = $orig;
    $orig[0] = 10;
    var_dump($copy[0]); //returns 10, should return 1
 [2016-05-07 23:50 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2016-05-07 23:50 UTC] requinix@php.net
https://3v4l.org/q3MhC and https://3v4l.org/e4Q81 respectively.

Close, but there's two details missing from your explanation:
1. Assignment of arrays copies the contents of the array, not its values. Semantics.
2. $x[2] and $orig[0] are not values themselves anymore but references to values.

That means copying $b=$x and $copy=$orig will result in a copy of the reference: a different reference itself though indicating the same referenced value.

Here's a PHP analogy of what happens under the hood:
- https://3v4l.org/MrNID $x and $b
- https://3v4l.org/GS6sU $orig and $copy (I suggest this one first)
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Thu Jul 03 11:01:34 2025 UTC