php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72543 different references behavior comparing to 5.5
Submitted: 2016-07-04 13:31 UTC Modified: 2016-07-06 17:49 UTC
From: [email protected] Assigned: dmitry (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 7.1.0alpha1 OS: *
Private report: No CVE-ID: None
 [2016-07-04 13:31 UTC] [email protected]
Description:
------------
Looks like references behavior has changed in 7.x comparing to 5.5.
First of all, once variable becomes reference, it never looses that flag, even though the second reference is already destroyed (see the first function "create_references").
Second, I'm able to change the original variable by passing its copy to a function and modifying it there, which is definitely counter-intuitive.
I expected the function to copy the variable to write, since it was not passed by reference, as that's what seems to be happening in PHP 5.5

Test script:
---------------
/* after this function all array elements become references */
function create_references(&$array) {
    $refs[] = &$array;
    foreach ($array as $key => $value) {
        create_references($array[$key]);
    }
}   

/* a copy is passed and then modified, which also modifies the original variable */
function change_copy($copy) {
    for ($i = 0; $i < 2; $i++) {
        $copy['b']['b'] = $copy['b']; //this causes recursion
    }
}   

$data = [
    'a' => [
        'b' => [],
    ],  
];  
 
create_references($data);
 
$copy = $data['a'];
var_dump($data);

change_copy($copy);
var_dump($data); //RECURSION

Expected result:
----------------
array(1) {
  ["a"]=>
  array(1) {
    ["b"]=>
    array(0) {
    }
  }
}
array(1) {
  ["a"]=>
  array(1) {
    ["b"]=>
    array(0) {
    }
  }
}


Actual result:
--------------
array(1) {
  ["a"]=>
  array(1) {
    ["b"]=>
    array(0) {
    }
  }
}
array(1) {
  ["a"]=>
  array(1) {
    ["b"]=>
    array(1) {
      ["b"]=>
      *RECURSION*
    }
  }
}


Patches

bug72543_3.diff (last revision 2016-07-06 00:31 UTC by [email protected])
bug72543_2.diff (last revision 2016-07-05 19:57 UTC by [email protected])
bug72543.diff (last revision 2016-07-05 10:45 UTC by [email protected])

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-07-04 13:32 UTC] [email protected]
-Status: Open +Status: Assigned -Assigned To: +Assigned To: dmitry
 [2016-07-04 15:52 UTC] [email protected]
@Dmitry, this reminds me of the patch I committed before(it was replaced though), http://pastebin.com/jHGEL7v8 the base idea here is, we should return non-reference in read context(FETCH_DIM_R), that patch should fix this problem as well

what do you think?
 [2016-07-04 17:02 UTC] [email protected]
In general, you fix is right, but it introduces an extra check on fast path, that is useless in almost all cases. I'll try to find a cheaper solution.
 [2016-07-05 03:17 UTC] [email protected]
yeah, I agree with that, but if cheaper fix is mess, than I prefer a clear one, besides, one UNEXPECT check should not change anything in performance.
 [2016-07-05 09:58 UTC] [email protected]
Before execution of the following statement $copy['b'] is a "dead" REFERENCE with refcount==1. 

$copy['b']['b'] = $copy['b'];

Right-side expression evaluated first, and incrementats REFERENCE refcount (it became 2). After that, it starts to behave as a real REFERENCE and is not separated during left-side expression evaluation.
 [2016-07-05 10:45 UTC] [email protected]
The following patch has been added/updated:

Patch Name: bug72543.diff
Revision:   1467715534
URL:        https://bugs.php.net/patch-display.php?bug=72543&patch=bug72543.diff&revision=1467715534
 [2016-07-05 11:19 UTC] [email protected]
does your patch also take care of

$arr = 'b';
$$arr['b']['b'] = $b['b']; ?
 [2016-07-05 19:57 UTC] [email protected]
The following patch has been added/updated:

Patch Name: bug72543_2.diff
Revision:   1467748668
URL:        https://bugs.php.net/patch-display.php?bug=72543&patch=bug72543_2.diff&revision=1467748668
 [2016-07-06 00:31 UTC] [email protected]
The following patch has been added/updated:

Patch Name: bug72543_3.diff
Revision:   1467765063
URL:        https://bugs.php.net/patch-display.php?bug=72543&patch=bug72543_3.diff&revision=1467765063
 [2016-07-06 17:46 UTC] [email protected]
Automatic comment on behalf of [email protected]
Revision: http://git.php.net/?p=php-src.git;a=commit;h=023b81259325c00012c0f703976c082be72dc5b9
Log: Fixed bug #72543 (Different references behavior comparing to PHP 5)
 [2016-07-06 17:46 UTC] [email protected]
-Status: Assigned +Status: Closed
 [2016-07-20 11:30 UTC] [email protected]
Automatic comment on behalf of [email protected]
Revision: http://git.php.net/?p=php-src.git;a=commit;h=023b81259325c00012c0f703976c082be72dc5b9
Log: Fixed bug #72543 (Different references behavior comparing to PHP 5)
 [2016-10-17 10:11 UTC] [email protected]
Automatic comment on behalf of [email protected]
Revision: http://git.php.net/?p=php-src.git;a=commit;h=023b81259325c00012c0f703976c082be72dc5b9
Log: Fixed bug #72543 (Different references behavior comparing to PHP 5)
 
PHP Copyright © 2001-2026 The PHP Group
All rights reserved.
Last updated: Tue Mar 17 11:00:01 2026 UTC