Bug #69072 [Opn]: bug when serializing classes that internally calls serialize
| From: | danack@php.net | Date: | Wed, 18 Feb 2015 15:08:42 +0000 |
| Subject: | Bug #69072 [Opn]: bug when serializing classes that internally calls serialize | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-190788@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=69072&edit=1
ID: 69072
Updated by: danack@php.net
Reported by: quamis+php at gmail dot com
Summary: bug when serializing classes that internally calls
serialize
Status: Open
Type: Bug
-Package: Class/Object related
+Package: Scripting Engine problem
Operating System: Linux
PHP Version: 5.6.5
Block user comment: N
Private report: N
New Comment:
Probably duplicate of https://bugs.php.net/bug.php?id=66052
Previous Comments:
------------------------------------------------------------------------
[2015-02-18 14:38:24] danack@php.net
This appears to be an issue when calling serialize within serialize.
The first and second \stdClass's created have the same ObjectHash. It appears that the second
internal call to serialize attempts to return a reference for the second stdclass to the first
stdclass. But that is not valid as the first serialization of stdclass is actually in a different
serialization call, and it's not meant to be a reference.
There is a simpler code example below; the class extending is not required to show the behaviour.
The output is:
loop 0: ObjectHash 00000000169f9afe0000000054338336 Received: O:8:"stdClass":0:{}
loop 0: Returning 'O:8:"stdClass":0:{}'
loop 1: ObjectHash 00000000169f9afe0000000054338336 Received: r:3; //This is wrong - it is not a
reference.
Object hash already exists - serialize is going to be sad.
borked, serialize of stdClass::__set_state(array(
)) returned r:3; which could not be unserialized.
<?php
class testClass_forSerialize implements Serializable {
public function serialize() {
static $count = 0;
static $objectHashes = [];
$ret = new \stdClass();
$serializedData = serialize($ret);
$objectHash = spl_object_hash($ret);
echo "loop $count: ObjectHash $objectHash Received:
".$serializedData."\n";
if (array_key_exists($objectHash, $objectHashes) == true) {
echo "Object hash already exists - serialize is going to be sad.\n";
}
$objectHashes[$objectHash] = $count;
if (@unserialize($serializedData) === false) {
printf(
"borked, serialize of %s returned %s which could not be unserialized.\n",
var_export($ret, true),
$serializedData
);
exit(0);
}
echo "loop $count: Returning '$serializedData'\n";
$count++;
return $serializedData;
}
public function unserialize($data) {
throw new \Exception("not relevant");
}
}
$list = [];
for ($i=0; $i<2; $i++) {
$list[] = new \testClass_forSerialize();
}
$ser = serialize($list);
------------------------------------------------------------------------
[2015-02-18 11:18:12] quamis+php at gmail dot com
Description:
------------
Consider the following example:
class A implements Serializable, defines serialize() as a serialized stdClass
class B extends A, adds 1 public member
index.php instantiates B and serializes it to be able to cache it/store it for future reference.
function serialize fails in this case, returns an invalid string. It should at least issue an
exception/warning.
If class A defines serialize() as a serialized array it will work as expected.
Test script:
---------------
Testcase: http://pastebin.com/6Hc60VbD , http://3v4l.org/SggeU
Working testcase (class A returns serialized array): http://pastebin.com/itzZY1En , http://3v4l.org/hIJE9
Expected result:
----------------
no exception should be thrown, and an actual representation of the class should be generated.
According to http://3v4l.org, this woked ok in PHP 5.3, and its
broken since PHP 5.4
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=69072&edit=1