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