Edit report at https://bugs.php.net/bug.php?id=72543&edit=1
ID: 72543
Patch added by: dmitry@php.net
Reported by: tony2001@php.net
Summary: different references behavior comparing to 5.5
Status: Assigned
Type: Bug
Package: Scripting Engine problem
Operating System: *
PHP Version: 7.1.0alpha1
Assigned To: dmitry
Block user comment: N
Private report: N
New Comment:
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
Previous Comments:
------------------------------------------------------------------------
[2016-07-05 09:58:48] dmitry@php.net
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 03:17:14] laruence@php.net
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-04 17:02:10] dmitry@php.net
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-04 15:52:37] laruence@php.net
@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 13:31:50] tony2001@php.net
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*
}
}
}
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=72543&edit=1