There are three ways serialization works in PHP:
- Basic serialization just dumps/restores all the properties of an object.
- Using __sleep() and __wakeup(), you can exclude some properties or do other code modifications.
- Using the Serializable interface lets you serialize to/from any arbitrary string. Often this string is created by calling serialize() recursively.
So what happens if you have an array with two objects, each of which contains the same third object?
class Foo { public $obj; public function __construct( $obj ) { $this->obj = $obj; } } $obj = new stdclass; $foo1 = new Foo( $obj ); $foo2 = new Foo( $obj ); $s = serialize( array( $foo1, $foo2 ) ); $data = unserialize( $s );
With either #1 or #2, it serializes that reference to $obj as a reference (code 'r') so when things are unserialized $data[0]->obj === $data[1]->obj.
a:2:{i:0;O:3:"Foo":1:{s:3:"obj";O:8:"stdClass":0:{}}i:1;O:3:"Foo":1:{s:3:"obj";r:3;}}
Originally, with method #3, it broke the reference so $data[0]->obj and $data[1]->obj would be clones of each other but would not be ===.
a:2:{i:0;C:3:"Foo":35:{a:1:{s:3:"obj";O:8:"stdClass":0:{}}}i:1;C:3:"Foo":35:{a:1:{s:3:"obj";O:8:"stdClass":0:{}}}}
It seems that was reported as PHP bug 36424. The issue was eventually fixed in PHP 5.4.0 by making recursive calls to serialize() and unserialize() share state.
a:2:{i:0;C:3:"Foo":35:{a:1:{s:3:"obj";O:8:"stdClass":0:{}}}i:1;C:3:"Foo":20:{a:1:{s:3:"obj";r:4;}}}
Unfortunately it seems HHVM never picked up that fix (HHVM bug 7253).
In T209582: Unable to serialize r:46: Id 46 out of range. and T210499: ErrorException from line 1159 of /srv/mediawiki/php-1.33.0-wmf.4/includes/Message.php: PHP Warning: Invalid argument supplied for foreach(), this seems to have caused issues with the cache of the sidebar from Skin::buildSidebar(). When someone testing with PHP 7.2 populates the cache, the serialized string uses a reference for Title objects inside of Message objects. When that serialized string is later fetched with HHVM, the lack of recursive state makes the unserialization fail.