php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #24630 extract with EXTR_REFS makes weird references
Submitted: 2003-07-12 20:47 UTC Modified: 2003-10-03 19:05 UTC
From: tater at potatoe dot com Assigned:
Status: Closed Package: Scripting Engine problem
PHP Version: 5.0.0b2-dev OS: OS X 10.2
Private report: No CVE-ID: None
 [2003-07-12 20:47 UTC] tater at potatoe dot com
Description:
------------
If you create an array by assigning its elements the value of a scalar variable (or, in PHP5, by using array_combine() with an array of keys and an array built with array_fill() or array_pad()), then extract(array, EXTR_REFS) will make that scalar into a reference, as well as making all the array elements references to the same... location? I don't know, they all end up pointing to the same thing, so that changing any one of them changes all of them.

This tests the same on the current PHP4 release and the latest CVS PHP5 code.


Reproduce code:
---------------
<?php
function trap()
{
    $tick = 0;
    $x = array('x1'=>$tick, 'x2'=>$tick, 'x3'=>0, 'x4'=>0);
    $y = array('y1'=>$tick, 'y2'=>$tick, 'y3'=>0, 'y4'=>0);
    var_dump(get_defined_vars());
    foreach ($x as $k => $v)
        $$k =& $x[$k];
    extract($y, EXTR_REFS);
    var_dump(get_defined_vars());
    $x1 = 1;
    $y1 = 2;
    $y3 = 4;
    var_dump(get_defined_vars());
    $tick = 5;
    var_dump(get_defined_vars());
}
trap();
?>

Expected result:
----------------
Changing $y1 should only change it and y['y1'].
Changing $tick should only change $tick.

Actual result:
--------------
Changing $y1 or $tick changes the other as well.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-07-12 21:04 UTC] sniper@php.net
Try search the bug database before submitting new reports..
there are couple of related reports still open. (mostly documentation issues..)

 [2003-07-12 21:40 UTC] tater at potatoe dot com
OK, tell me this is bogus:
-------------------------------
<?php
function trap1()
{
        $a = 10;
        $b = array('x'=>$a);
        $x =& $b['x'];
        $x = 5;
        var_dump(get_defined_vars());
}
trap1();
function trap2()
{
        $a = 10;
        $b = array('x'=>$a);
        extract($b, EXTR_REFS);
        $x = 5;
        var_dump(get_defined_vars());
}
trap2();
?>
In first function, $a is unchanged. In second, it is altered. They should behave the same way. It is only
extract() making the difference.
 [2003-07-12 22:34 UTC] sniper@php.net
IMO, it's exactly how it's supposed to work.
To emulate the EXTR_REFS:

<?php
function trap1()
{
        $a = 10;
        $b = array('x'=>&$a);
        $x =& $b['x'];
        $x = 5;
        var_dump(get_defined_vars());
}
trap1();

 [2003-07-12 23:10 UTC] tater at potatoe dot com
But '$b = array('x'=>&$a);' is quite different from
'$b = array('x'=>$a);', and extract() is retroactively
altering the definition of $b. $b['x'] should just be a copy
of $a. I think it's just a symbol table problem. If I do:

$a = 10;
$b['x'] = $a;
$a = 10;
extract($b, EXTR_REFS);
$x = 5;

now $a is not changed. If $b['x'] really was &$a, that would not be the case.
 [2003-10-03 19:05 UTC] sniper@php.net
Seems to be fixed in CVS now.

 
PHP Copyright © 2001-2026 The PHP Group
All rights reserved.
Last updated: Sat Feb 07 17:00:01 2026 UTC