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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
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

Pull Requests

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-2025 The PHP Group
All rights reserved.
Last updated: Wed Feb 05 16:01:30 2025 UTC