Bug #72229 [NEW]: Wrong reference when serialize/unserialize an object

From: Date: Tue, 17 May 2016 08:22:29 +0000
Subject: Bug #72229 [NEW]: Wrong reference when serialize/unserialize an object
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-201146@lists.php.net to get a copy of this message
From:             email at rodrigo-supper dot de
Operating system: Ubuntu 14.04; Windows 7; ...
PHP version:      7.0.6
Package:          *General Issues
Bug Type:         Bug
Bug description:Wrong reference when serialize/unserialize an object

Description:
------------
The Bug concerns serialization of an object: in certain cases a "real"
reference (with a '&' like &$x) is wrongly introduced.
In terms of the string as an output of the serialization: instead of an
'r:' an 'R:' is used.

Run the test script twice: first without the marked two lines (see code)
and second with these two lines. 

What is expected:
In the sample code the $Obj1 shows the expected result. $Obj2 should
also show this result.

What the actual result is:
With the two marked lines uncommented in code, $Obj2 shows a wrong
result.
 
DESCRIPTION:
Without the two lines in the contructor all is correct. The produced
string ($txt1) by serialization is:
    O:2:"C1":2:{s:4:"arr1";a:1:{i:0;r:1;}s:4:"arr2";a:1:{i:0;r:1;}}
Unserialization of this string creates an object ($Obj2) which is
identical with the original object ($Obj1). This object "behaves" quite
correct: after assigning the value '50' to its member arr2[0] the
content of its member arr1[0] remains unchanged, i.e. it still holds a
reference to the object itself ($Obj2). That's correct because in the
constructor there is an assigning "by value", i.e. $this->arr2[0] does
NOT refer to the array element $this->arr1[0].

With the two lines in the constructor the result is wrong. The produced
string ($txt1) by serialization is:
    O:2:"C1":2:{s:4:"arr1";a:1:{i:0;R:1;}s:4:"arr2";a:1:{i:0;r:1;}}
Notice: the occurence of the first 'r:' in the middle of the string
changed to 'R:' (from lower case to upper case letter!).
The two lines simply introduce a reference of a local variable to
arr1[0] and remove (unset) it immediately after. Therefore the resulting
object should be exactly the same as without these two lines. But the
output string of the serialization now shows a "real" reference from
arr2[0] to arr1[0]! The concequence of this bug is, that after
unserialization (creation of an object from the serialized string) there
is a "connection" (a real reference) from the member arr2[0] to the
member arr1[0], which was not the case in the original object! Now
changing the content of arr2[0] also (wrongly) changes the content of
arr1[0].

It seems that this bug only occures when a recursion exists. The line
'$this->arr1[0] = $this;' in the constructor introduces this recursion.
This was done here in this simple way only for demonstration purpose.
The bug also occures when the recursion exists much more
complicate/indirect (i.e. via a chain of many other objects) and also if
it's done in any other method of the objects than the constructor. 
Because recursion is needed for this bug, as a concequence the reported
bug only occures when an object is assigned to the member variable. The
bug does not occure when simple values are assigned (because values
can't form a recursion).

I consider this bug as very serious! Because PHP uses serialization for
saving (session-)variables between script calls all objects containing a
recursion will be wrong after repetitive script calls!


Test script:
---------------
<?php
class C1
{
    public $arr1 = array();
    public $arr2 = array();
    public function __construct()
    {
        $this->arr1[0] = $this;
        $this->arr2[0] = $this->arr1[0];
        // ***** Run the test without and with the following two lines:
        $var1 = &$this->arr1[0];  // Set a reference...
        unset($var1);             // ... and unset it. 
    }
}
echo '<pre>';
$Obj1 = new C1();
$txt1 = serialize($Obj1);
$Obj2 = unserialize($txt1);
$Obj1->arr2[0] = 50;
print_r($Obj1);
$Obj2->arr2[0] = 50;
print_r($Obj2);
echo '</pre>';
?>

Expected result:
----------------
C1 Object
(
    [arr1] => Array
        (
            [0] => C1 Object
 *RECURSION*
        )

    [arr2] => Array
        (
            [0] => 50
        )

)
C1 Object
(
    [arr1] => Array
        (
            [0] => C1 Object
 *RECURSION*
        )

    [arr2] => Array
        (
            [0] => 50
        )

)

Actual result:
--------------
C1 Object
(
    [arr1] => Array
        (
            [0] => C1 Object
 *RECURSION*
        )

    [arr2] => Array
        (
            [0] => 50
        )

)
C1 Object
(
    [arr1] => Array
        (
            [0] => 50
        )

    [arr2] => Array
        (
            [0] => 50
        )

)

-- 
Edit bug report at https://bugs.php.net/bug.php?id=72229&edit=1
-- 
Try a snapshot (PHP 5.4):   https://bugs.php.net/fix.php?id=72229&r=trysnapshot54
Try a snapshot (PHP 5.5):   https://bugs.php.net/fix.php?id=72229&r=trysnapshot55
Try a snapshot (trunk):     https://bugs.php.net/fix.php?id=72229&r=trysnapshottrunk
Fixed in SVN:               https://bugs.php.net/fix.php?id=72229&r=fixed
Fixed in release:           https://bugs.php.net/fix.php?id=72229&r=alreadyfixed
Need backtrace:             https://bugs.php.net/fix.php?id=72229&r=needtrace
Need Reproduce Script:      https://bugs.php.net/fix.php?id=72229&r=needscript
Try newer version:          https://bugs.php.net/fix.php?id=72229&r=oldversion
Not developer issue:        https://bugs.php.net/fix.php?id=72229&r=support
Expected behavior:          https://bugs.php.net/fix.php?id=72229&r=notwrong
Not enough info:            https://bugs.php.net/fix.php?id=72229&r=notenoughinfo
Submitted twice:            https://bugs.php.net/fix.php?id=72229&r=submittedtwice
register_globals:           https://bugs.php.net/fix.php?id=72229&r=globals
PHP 4 support discontinued: https://bugs.php.net/fix.php?id=72229&r=php4
Daylight Savings:           https://bugs.php.net/fix.php?id=72229&r=dst
IIS Stability:              https://bugs.php.net/fix.php?id=72229&r=isapi
Install GNU Sed:            https://bugs.php.net/fix.php?id=72229&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=72229&r=float
No Zend Extensions:         https://bugs.php.net/fix.php?id=72229&r=nozend
MySQL Configuration Error:  https://bugs.php.net/fix.php?id=72229&r=mysqlcfg



Thread (2 messages)

« previous php.bugs (#201146) next »