Bug #72543 [Asn]: different references behavior comparing to 5.5

From: Date: Tue, 05 Jul 2016 09:58:50 +0000
Subject: Bug #72543 [Asn]: different references behavior comparing to 5.5
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-202059@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=72543&edit=1

 ID:                 72543
 Updated 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:

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.


Previous Comments:
------------------------------------------------------------------------
[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


Thread (12 messages)

« previous php.bugs (#202059) next »