1--TEST--
2Bug #65806 (unserialize fails with object which is referenced multiple times)
3--FILE--
4<?php
5class myObjA {}
6class myObjB {
7    public $attrA;
8    public $attrB;
9}
10class myObjC {
11    public $attrC;
12    public $attrD;
13}
14class myList {
15    private $_serialized;
16    private $_obj;
17
18    public function __construct($obj)
19    {
20        $this->_obj = $obj;
21        $this->_serialized = serialize($this->_obj);
22    }
23    public function get()
24    {
25        return $this->_obj;
26    }
27    public function __sleep()
28    {
29        $this->_serialized = serialize($this->_obj);
30        return array(
31            "\0" . __CLASS__ . "\0_serialized",
32        );
33    }
34    public function __wakeup()
35    {
36        $this->_obj = unserialize($this->_serialized);
37    }
38}
39
40echo "SCRIPT START" . PHP_EOL;
41
42$objA = new myObjA();
43$objB = new myObjB();
44$objC = new myObjC();
45
46$objB->attrA = new ArrayIterator();
47$objB->attrB = $objA;
48
49$objC->attrC = $objB;
50$objC->attrD = $objA;
51
52$list = new myList($objC);
53
54echo 'check ' . check($list->get()) . PHP_EOL;
55
56echo "start serialize/unserialize" . PHP_EOL;
57$newList = unserialize(serialize($list));
58echo "finish serialize/unserialize" . PHP_EOL;
59
60//after unserialize the property myObjC::attrD is null instead of expected object
61echo 'check ' . check($newList->get()) . PHP_EOL;
62
63echo "SCRIPT END" . PHP_EOL ;
64
65function check(myObjC $obj) {
66
67    if (!is_object($obj->attrC)) {
68        return 'failed (myObjC::attrC => ' . var_export($obj->attrC, true) . ')';
69    }
70    if (!is_object($obj->attrD)) {
71        return 'failed (myObjC::attrD => ' . var_export($obj->attrD, true) . ')';
72    }
73    return 'successful';
74}
75?>
76--EXPECT--
77SCRIPT START
78check successful
79start serialize/unserialize
80finish serialize/unserialize
81check successful
82SCRIPT END
83