Edit report at https://bugs.php.net/bug.php?id=62634&edit=1
ID: 62634 Updated by: m...@php.net Reported by: phplists at stanvassilev dot com Summary: Incorrect serialization with circular references -Status: Open +Status: Analyzed Type: Bug Package: Scripting Engine problem Operating System: Any PHP Version: 5.4.5 Block user comment: N Private report: N Previous Comments: ------------------------------------------------------------------------ [2013-03-16 18:09:15] ni...@php.net The reason this happens is that serialize accepts by value, and as such the outer array will be a separated and will be different from the one that is references from within the array. This can be fixed by marking the serialize argument as ZEND_SEND_PREFER_REF. Not sure if this should be done or not. ------------------------------------------------------------------------ [2012-07-25 13:25:23] f...@php.net Maybe related to https://bugs.php.net/bug.php?id=62189 ------------------------------------------------------------------------ [2012-07-22 21:58:45] phplists at stanvassilev dot com There's a small error in my code example, please replace this line: $duplicate = unserialize(serialize($x)); With this line: $duplicate = unserialize(serialize($original)); ------------------------------------------------------------------------ [2012-07-22 21:54:54] phplists at stanvassilev dot com Description: ------------ The documentation says references and circular references should serialize properly. I've found that serialize would first copy the referenced variable, before detecting the reference. This not only doubles the serialized output, but produced incorrect copy when unserialized. Test script: --------------- $original = array('hello'); $original[] = & $original; echo serialize($original); // Output (notice the duplication): // "a:2:{i:0;s:5:"hello";i:1;a:2:{i:0;s:5:"hello";i:1;R:3;}}" $duplicate = unserialize(serialize($x)); // Now I modify both the original and the duplicate in an identical way. // But I get different results, because the duplicate points to a copy of // itself, instead of pointing to itself. $original[0] = 'world'; $duplicate[0] = 'world'; var_dump($original); // Produces (notice it says "world" both times, i.e. it points to itself): // array(2) { [0]=> string(5) "world" [1]=> &array(2) { [0]=> string(5) "world" [1]=> *RECURSION* } } var_dump($duplicate); // Produces (notice the second time it says "hello" i.e. it's a copy): // array(2) { [0]=> string(5) "world" [1]=> &array(2) { [0]=> string(5) "hello" [1]=> *RECURSION* } } Expected result: ---------------- There should be NO copies of "hello" left: array(2) { [0]=> string(5) "world" [1]=> &array(2) { [0]=> string(5) "world" [1]=> *RECURSION* } } There should be NO duplication in the serialized output: "a:2:{i:0;s:5:"hello";i:1;???;}" (Fill-in the "???" appropriately :) ) Actual result: -------------- A copy of "hello" is left: array(2) { [0]=> string(5) "world" [1]=> &array(2) { [0]=> string(5) "hello" [1]=> *RECURSION* } } There is duplication in the serialized output: "a:2:{i:0;s:5:"hello";i:1;a:2:{i:0;s:5:"hello";i:1;R:3;}}" ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=62634&edit=1