php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #52521 self-referenced array is copied instead of referenced after serialization
Submitted: 2010-08-03 09:14 UTC Modified: 2017-01-01 11:33 UTC
Votes:2
Avg. Score:4.5 ± 0.5
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:2 (100.0%)
From: martin dot leucht at gmail dot com Assigned:
Status: Duplicate Package: Arrays related
PHP Version: 5.3.3 OS: WIN32
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: martin dot leucht at gmail dot com
New email:
PHP Version: OS:

 

 [2010-08-03 09:14 UTC] martin dot leucht at gmail dot com
Description:
------------
When trying to serialize -> unserialize a structure (i.e. array) containing a child (or a subordinate child) referencing the root element (meaning the structure to serialize) itself, it will be lost afterwards.
This leads to annoying misbehaviour and memory abuse.

If I unserialize the "correct" serialized string, it works correctly. May be its a bug in reference creation?!

Test script:
---------------
$Array = array(
	'a' => 1
);
$Array['b'] = &$Array;

echo "print_r():\n";
echo "----------\n";
print_r($Array);
echo "\n";

echo "serialize():\n";
echo "------------\n";
echo serialize($Array);
echo "\n\n";

echo "print_r(unserialize(serialize())):\n";
echo "----------------------------------\n";
print_r(unserialize(serialize($Array)));
echo "\n";

echo "*** modify referenced value ***\n\n";

$Array['a'] = 2;

echo "print_r():\n";
echo "----------\n";
print_r($Array);
echo "\n";

echo "*** modify re-serialized refererenced value ***\n\n";

$Array['a'] = 1;
$Array = unserialize(serialize($Array));

$Array['a'] = 2;

echo "print_r():\n";
echo "----------\n";
print_r($Array);
echo "\n";

echo "*** using correct value ***\n\n";

$Array = unserialize('a:2:{s:1:"a";i:1;s:1:"b";R:1;}');
echo "print_r():\n";
echo "----------\n";
print_r($Array);
echo "\n";

Expected result:
----------------
print_r():
----------
Array
(
    [a] => 1
    [b] => Array
 *RECURSION*

)

serialize():
------------
a:2:{s:1:"a";i:1;s:1:"b";R:1;}

print_r(unserialize(serialize())):
----------------------------------
Array
(
    [a] => 1
    [b] => Array
 *RECURSION*

)

*** modify referenced value ***

print_r():
----------
Array
(
    [a] => 2
    [b] => Array
 *RECURSION*

)

*** modify re-serialized refererenced value ***

print_r():
----------
Array
(
    [a] => 2
    [b] => Array
 *RECURSION*

)

*** using correct value ***

print_r():
----------
Array
(
    [a] => 1
    [b] => Array
 *RECURSION*
)



Actual result:
--------------
print_r():
----------
Array
(
    [a] => 1
    [b] => Array
        (
            [a] => 1
            [b] => Array
 *RECURSION*
        )

)

serialize():
------------
a:2:{s:1:"a";i:1;s:1:"b";a:2:{s:1:"a";i:1;s:1:"b";R:3;}}

print_r(unserialize(serialize())):
----------------------------------
Array
(
    [a] => 1
    [b] => Array
        (
            [a] => 1
            [b] => Array
 *RECURSION*
        )

)

*** modify referenced value ***

print_r():
----------
Array
(
    [a] => 2
    [b] => Array
        (
            [a] => 2
            [b] => Array
 *RECURSION*
        )

)

*** modify re-serialized refererenced value ***

print_r():
----------
Array
(
    [a] => 2
    [b] => Array
        (
            [a] => 1
            [b] => Array
 *RECURSION*
        )

)

*** using correct value ***

print_r():
----------
Array
(
    [a] => 1
    [b] => Array
 *RECURSION*
)



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-08-03 09:27 UTC] martin dot leucht at gmail dot com
I have to correct myself:

> If I unserialize the "correct" serialized string, it works correctly.
It just works for print_r() afterwards, but if I do some stuff on the referenced value it creates even more confusing structures.

Test script:
------------
echo "*** using correct value ***\n\n";

$Array = unserialize('a:2:{s:1:"a";i:1;s:1:"b";R:1;}');
echo "print_r():\n";
echo "----------\n";
print_r($Array);
echo "\n";

$Array['b']['a'] = 2;
echo "print_r():\n";
echo "----------\n";
print_r($Array);
echo "\n";

Actual result
-------------
*** using correct value ***

print_r():
----------
Array
(
    [a] => 1
    [b] => Array
 *RECURSION*
)

print_r():
----------
Array
(
    [a] => 1
    [b] => Array
        (
            [a] => 2
            [b] => Array
                (
                    [a] => 1
                    [b] => Array
 *RECURSION*
                )

        )

)

Expected result
---------------
*** using correct value ***

print_r():
----------
Array
(
    [a] => 1
    [b] => Array
 *RECURSION*
)

print_r():
----------
Array
(
    [a] => 2
    [b] => Array
 *RECURSION*
)
 [2010-08-03 09:53 UTC] mike@php.net
-Status: Open +Status: Feedback
 [2010-08-03 09:53 UTC] mike@php.net
Please try using this snapshot:

  http://snaps.php.net/php-trunk-latest.tar.gz
 
For Windows:

  http://windows.php.net/snapshots/

Could you please try a trunk snapshot, IIRC this problem might be fixed already.

Thanks.
 [2010-08-03 13:23 UTC] martin dot leucht at gmail dot com
Sorry, but there are no builds on the Windows snapshots page and as I do not maintain a PHP build environment (nor am currently willing to do so due to a lack of time) I can not test it right now.
Could you please give me a hint when the snapshot builds are available or if anyone else can do this test using the given test script above.
 [2010-08-04 22:03 UTC] martin dot leucht at googlemail dot com
Okay, I finally made it though. I setup a build environment, built the latest dev-version of PHP and ran the test script. But still: identical results.

Please tell me how can I provide some help or assistence to solve this issue?!
 [2010-08-04 22:50 UTC] martin dot leucht at googlemail dot com
It seems it is array-related. The same thing using the stdclass works fine.

Test script:
------------
<?php

$Object = (object)array(
	'a' => 1,
	'b' => &$Object,
);
print_r($Object);

$Array = array(
	'a' => 1,
	'b' => &$Array,
);
print_r($Array);

$Array = unserialize(serialize($Array));
$Object = unserialize(serialize($Object));

$Object->b->a = 2;
print_r($Object);

$Array['b']['a'] = 2;
print_r($Array);

?>

Actual result:
--------------
stdClass Object
(
    [a] => 1
    [b] => stdClass Object
 *RECURSION*
)
Array
(
    [a] => 1
    [b] => Array
        (
            [a] => 1
            [b] => Array
 *RECURSION*
        )

)
stdClass Object
(
    [a] => 2
    [b] => stdClass Object
 *RECURSION*
)
Array
(
    [a] => 1
    [b] => Array
        (
            [a] => 2
            [b] => Array
 *RECURSION*
        )

)
 [2010-08-05 16:18 UTC] martin dot leucht at gmail dot com
-Summary: serialize() loses reference to root +Summary: self-referenced array is copied instead of referenced after serialization -Status: Feedback +Status: Open -Package: *Programming Data Structures +Package: Arrays related
 [2010-08-05 16:18 UTC] martin dot leucht at gmail dot com
// updated bug information
 [2017-01-01 11:33 UTC] nikic@php.net
-Status: Open +Status: Duplicate
 [2017-01-01 11:33 UTC] nikic@php.net
Marking as duplicate of the newer bug #62634, which contains a comment explaining why this happens.
 
PHP Copyright © 2001-2018 The PHP Group
All rights reserved.
Last updated: Sat Nov 17 03:01:25 2018 UTC