Bug #72229 [Opn->Csd]: Wrong reference when serialize/unserialize an object
| From: | laruence@php.net | Date: | Tue, 17 May 2016 09:40:49 +0000 |
| Subject: | Bug #72229 [Opn->Csd]: Wrong reference when serialize/unserialize an object | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-201148@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=72229&edit=1
ID: 72229
Updated by: laruence@php.net
Reported by: email at rodrigo-supper dot de
Summary: Wrong reference when serialize/unserialize an object
-Status: Open
+Status: Closed
Type: Bug
Package: *General Issues
Operating System: Ubuntu 14.04; Windows 7; ...
PHP Version: 7.0.6
Block user comment: N
Private report: N
New Comment:
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=7989db975f325d83b461a46c3dc75a81fcc27795
Log: Fixed bug #72229 (Wrong reference when serialize/unserialize an object)
Previous Comments:
------------------------------------------------------------------------
[2016-05-17 08:22:19] email at rodrigo-supper dot de
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 this bug report at https://bugs.php.net/bug.php?id=72229&edit=1