php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #63865 php unset local reference affecting global scope
Submitted: 2012-12-28 04:53 UTC Modified: 2012-12-30 15:33 UTC
Votes:4
Avg. Score:3.2 ± 0.4
Reproduced:3 of 3 (100.0%)
Same Version:1 (33.3%)
Same OS:1 (33.3%)
From: petermiller1986 at gmail dot com Assigned: krakjoe (profile)
Status: Closed Package: *General Issues
PHP Version: 5.3.20 OS: ubuntu 10.04
Private report: No CVE-ID: None
 [2012-12-28 04:53 UTC] petermiller1986 at gmail dot com
Description:
------------
i have come across some very strange php behaviour. an unset which should occur within local scope is affecting the scope of the caller function. if you run the test script you will see that the value 'first value' has been unset from the $data array in the global scope. however if you comment out the $in_ref =& $in['level1']; line then the result changes (and it shouldn't i think).

is this intended behaviour of php or a bug?


Test script:
---------------
<?php
function should_not_alter($in)
{
    $in_ref =& $in['level1']; //try commenting out this line to see the output change
    should_only_unset_locally($in);
    return $in;
}
function should_only_unset_locally($in)
{
    unset($in['level1']['level2_0']);
}
$data = array('level1' => array('level2_0' => 'first value', 'level2_1' => 'second value'));
$data = should_not_alter($data);
print_r($data);
?>

Expected result:
----------------
Array
(
    [level1] => Array
        (
            [level2_0] => first value
            [level2_1] => second value
        )

)

Actual result:
--------------
Array
(
    [level1] => Array
        (
            [level2_1] => second value
        )

)


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-12-30 15:33 UTC] krakjoe@php.net
You set the data in the global scope with the return of the function.
Your unset function does not receive the array by reference.
See the code below, commenting out the reference makes no difference.

<?php
function should_not_alter($in)
{
    $in_ref = &$in['level1']; //try commenting out this line to see the output 
change

    should_only_unset_locally($in);

    return $in;
}

function should_only_unset_locally(&$in)
{
    unset($in['level1']['level2_0']);
}

$data[0] = array(
    'level1' => array(
        'level2_0' => 'first value',
        'level2_1' => 'second value'
    )
);

$data[1]=should_not_alter($data[0]);

print_r($data);
?>
 [2012-12-30 15:33 UTC] krakjoe@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: krakjoe
 [2012-12-30 23:19 UTC] corbin dot h dot 10 at gmail dot com
@krakjoe

The problem is that a function where something is passed by value should never 
permute the value passed.

You would never expect $x = ...; function f($var) { ... } f($x); to change $x.  
That is unintuitive behavior.

A better illustration of it may be as follows:

<?php

function weird($arr)
{
	$arr['foo'] = 'baz';
}

$a = array('foo' => 'bar', 'moo' => 'cow');

//This will leave foo as bar, as is expected
weird($a);
print_r($a);

$ref = &$a['foo'];

//Now it will change foo to baz
//This seems like very unexpected behavior?
weird($a);
print_r($a);
 [2013-01-04 04:32 UTC] petermiller1986 at gmail dot com
@krackjoe, did you try running the code i originally posted both with the line commented out and not commented out? they should give the same result, regardless of the commenting out, however they do not.

thanks for your time.
peter
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Fri Mar 14 10:01:32 2025 UTC