Bug #55801 [Ana->Fbk]: Behavior of unserialize has changed
| From: | mike@php.net | Date: | Thu, 13 Oct 2011 14:39:40 +0000 |
| Subject: | Bug #55801 [Ana->Fbk]: Behavior of unserialize has changed | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-164299@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=55801&edit=1
ID: 55801
Updated by: mike@php.net
Reported by: mapi at pdepend dot org
Summary: Behavior of unserialize has changed
-Status: Analyzed
+Status: Feedback
Type: Bug
Package: Variables related
Operating System: Linux (Fedora 15)
PHP Version: 5.4.0beta1
Assigned To: mike
Block user comment: N
Private report: N
New Comment:
Could you try attached patch, please?
Previous Comments:
------------------------------------------------------------------------
[2011-10-13 14:39:10] mike@php.net
The following patch has been added/updated:
Patch Name: fix-serialize-in-sleep-and-wakeup
Revision: 1318516750
URL: https://bugs.php.net/patch-display.php?bug=55801&patch=fix-serialize-in-sleep-and-wakeup&revision=1318516750
------------------------------------------------------------------------
[2011-10-04 16:34:49] mapi at pdepend dot org
To answer your question, I did't know my initial intention about the __temp__
property, but I remember that there was a reason. But it seems that this property
is obsolete now.
------------------------------------------------------------------------
[2011-10-04 16:20:39] mapi at pdepend dot org
Cool that you came up with a reproducable, I have tried it for a couple of hours
and didn't get a working reproducable outside of PHP_Depend.
But is it such an uncommon use case to serialize/unserialize additional data in
an object's __sleep() or __wakeup() method?
------------------------------------------------------------------------
[2011-10-04 14:20:46] mike@php.net
So, after digging a lot, I can only see two solutions:
- either disallow serialize/unserialize in __sleep/__wakeup
- or revert r299770 which introduced a "persistent" state for serialize() which
allowed objects which implement the Serializable interface to keep reference
info through recursive calls to serialize(), see FR #36424
The issue can probably be seen as follows:
serialize(obj)
-> obj->__sleep does serialize() (in your code)
-> then internally serialize(obj->prop) happens
unserialize(obj)
-> internally unserialize(obj->prop) is done
-> obj->__wakeup is called which does unserialize() (your code)
As you can see the IDs of the referenced objects when unserializing cannot match
the IDs at serialization time, because of the mixed up call order.
------------------------------------------------------------------------
[2011-10-04 08:25:40] mike@php.net
Ok, now got a reproduce case:
<?php
class node {
protected $parent;
protected $nodes = array();
protected $path;
protected $temp;
function __toString() {
return $this->parent ? $this->parent . "/" . $this->path :
$this->path;
}
function __construct(node $parent = null, $path = ".") {
$this->parent = $parent;
$this->path = $path;
if (is_dir($this)) foreach (scandir($this) as $p) {
if ($p[0] != ".") {
$this->nodes[] = new node($this, $p);
}
}
}
function __sleep() {
$this->temp = serialize($this->nodes);
return array("path", "temp");
}
function __wakeup() {
$this->nodes = unserialize($this->temp);
$this->temp = null;
foreach ($this->nodes as $n) {
$n->parent = $this;
}
}
function createWeirdConnections() {
foreach ($this->nodes as $n) {
$a = $this->nodes;
shuffle($a);
$n->nodes[] = current($a);
}
}
}
$tree = new node(null, @$_SERVER["argv"][1] ?: ".");
$tree->createWeirdConnections();
$s = serialize($tree);
$temp = unserialize($s);
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=55801
--
Edit this bug report at https://bugs.php.net/bug.php?id=55801&edit=1