Bug #46140 [Opn->Csd]: Unserializing with __wakeup that removes child causes subsequent refs to shift
| From: | cmb@php.net | Date: | Sun, 24 May 2015 18:06:51 +0000 |
| Subject: | Bug #46140 [Opn->Csd]: Unserializing with __wakeup that removes child causes subsequent refs to shift | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-192863@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=46140&edit=1
ID: 46140
Updated by: cmb@php.net
Reported by: ehassler at synapsestudios dot com
Summary: Unserializing with __wakeup that removes child
causes subsequent refs to shift
-Status: Open
+Status: Closed
Type: Bug
Package: Class/Object related
Operating System: *
PHP Version: 5.2.8
-Assigned To:
+Assigned To: cmb
Block user comment: N
Private report: N
New Comment:
Fixed as of PHP 5.4.39, 5.5.23 and 5.6.7.
Previous Comments:
------------------------------------------------------------------------
[2014-06-02 20:49:43] cmbecker69 at gmx dot de
It seems this issue will be solved in PHP 5.7, see
<http://3v4l.org/jpqW8>.
------------------------------------------------------------------------
[2008-10-29 00:18:41] ehassler at synapsestudios dot com
Very similar problem in PHP_VERSION === '5.2.7RC3-dev' under Windows.
I ran my test script and got out:
array(3) {
[0]=>
object(B)#5 (1) {
["value"]=>
object(C)#1 (0) {
}
}
[1]=>
object(B)#6 (1) {
["value"]=>
object(B)#6 (1) {
["value"]=>
*RECURSION*
}
}
[2]=>
object(B)#7 (1) {
["value"]=>
object(B)#6 (1) {
["value"]=>
object(B)#6 (1) {
["value"]=>
*RECURSION*
}
}
}
}
------------------------------------------------------------------------
[2008-09-21 02:33:42] ehassler at synapsestudios dot com
After adding static $instance2 to class C, and changing the __wakeup to this:
function __wakeup()
{
if($this->value instanceof C)
{
C::$instance2 = $this->value;
$this->value = C::$instance;
}
}
I get the expected behavior. So, I guess, you know, hope that helps.
------------------------------------------------------------------------
[2008-09-21 02:22:58] ehassler at synapsestudios dot com
Description:
------------
During unserialization of a 3 deep non-recursive but not-a-tree data structure (more like a diamond)
where, on nodes in level 2 a __wakeup causes all references to a child node of a certain class to be
removed, when that child node would occur in subsequent level 2 nodes' child spots, the
reference instead now points to the next level 2 node instead of any level 3 node. More
specifically, it points to the first level 2 node after the one that removed said child.
The sample code makes it more clear.
Reproduce code:
---------------
class B {
public $value;
function __construct($value){ $this->value = $value; }
function __wakeup()
{
if($this->value instanceof C)
$this->value = C::$instance;
}
}
class C { static public $instance; }
C::$instance = new C;
$A = array( new B(C::$instance), new B(C::$instance), new B(C::$instance) );
var_dump($A);
$A = unserialize(serialize($A));
var_dump($A);
Expected result:
----------------
array
0 =>
object(B)[2]
public 'value' =>
object(C)[1]
1 =>
object(B)[3]
public 'value' =>
object(C)[1]
2 =>
object(B)[4]
public 'value' =>
object(C)[1]
array
0 =>
object(B)[5]
public 'value' =>
object(C)[1]
1 =>
object(B)[7]
public 'value' =>
object(C)[1]
2 =>
object(B)[8]
public 'value' =>
object(C)[1]
Actual result:
--------------
array
0 =>
object(B)[2]
public 'value' =>
object(C)[1]
1 =>
object(B)[3]
public 'value' =>
object(C)[1]
2 =>
object(B)[4]
public 'value' =>
object(C)[1]
array
0 =>
object(B)[5]
public 'value' =>
object(C)[1]
1 =>
object(B)[6]
public 'value' =>
&object(B)[6]
2 =>
object(B)[7]
public 'value' =>
object(B)[6]
public 'value' =>
&object(B)[6]
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=46140&edit=1