From: miau dot jp at gmail dot com Operating system: any PHP version: 5.3.14 Package: Class/Object related Bug Type: Bug Bug description:serialize() generates wrong reference to the object
Description: ------------ With many (more than 21760 on 32-bit environment) objects on a PHP environment, serialize() occasionally generates wrong reference to object. When an object is passed to serialize() function, a hash value is caluculated. If the hash value has been seen before, the object is considered as the same object that is already serialized and serialize() generates the reference representation such as "r:2". Hash value is calculated with the logic below. https://github.com/php/php-src/blob/PHP-5.3.14/ext/standard/var.c#L545 (((size_t)Z_OBJCE_P(var) << 5) | ((size_t)Z_OBJCE_P(var) >> (sizeof(long) * 8 - 5))) # always 0 on 32-bit environment + (long) Z_OBJ_HANDLE_P(var) Z_OBJCE_P(var) is the address of zend_class_entry structure for each class. Z_OBJ_HANDLE_P(var) is the sequencial number that begins with 1 and increased by 1 for each object. sizeof(zend_class_entry) is 680 on 32-bit environment. When you declare two empty class A and B, and construct object $a and $b, hash values of two object can be the same. |object|Z_OBJ_HANDLE_P(var) |class|Z_OBJCE_P(var)|hash value | |------+--------------------+-----+--------------+--------------------+ |$b |1 |B |x + 680 |((x + 680) << 5) + 1| |(any) |2 | | | | |(any) |3 | | | | | |: | | | | |$a |1 + (680 << 5) |A |x |((x + 680) << 5) + 1| In such a case, serialize() generates wrong reprensenation. Test script: --------------- <?php class A {} class B {} $dummy = array(); $b = new B(); for ($i = 1; $i <= 100000; $i++) { $a = new A(); $s = serialize(array($b, $a)); if (strpos($s, 'r:') !== false) { echo "conflict occures at the {$i}th loop!\n"; echo "$s\n"; var_dump(unserialize($s)); exit; } $dummy[] = $a; } echo "not conflict with each other\n"; Expected result: ---------------- a:2:{i:0;O:1:"B":0:{}i:1;O:1:"A":0:{}} array(2) { [0] => class B#100002 (0) { } [1] => class A#100003 (0) { } } Actual result: -------------- conflict occures at the 21760th loop! a:2:{i:0;O:1:"B":0:{}i:1;r:2;} array(2) { [0] => class B#21762 (0) { } [1] => class B#21762 (0) { } } -- Edit bug report at https://bugs.php.net/bug.php?id=62373&edit=1 -- Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=62373&r=trysnapshot54 Try a snapshot (PHP 5.3): https://bugs.php.net/fix.php?id=62373&r=trysnapshot53 Try a snapshot (trunk): https://bugs.php.net/fix.php?id=62373&r=trysnapshottrunk Fixed in SVN: https://bugs.php.net/fix.php?id=62373&r=fixed Fixed in SVN and need be documented: https://bugs.php.net/fix.php?id=62373&r=needdocs Fixed in release: https://bugs.php.net/fix.php?id=62373&r=alreadyfixed Need backtrace: https://bugs.php.net/fix.php?id=62373&r=needtrace Need Reproduce Script: https://bugs.php.net/fix.php?id=62373&r=needscript Try newer version: https://bugs.php.net/fix.php?id=62373&r=oldversion Not developer issue: https://bugs.php.net/fix.php?id=62373&r=support Expected behavior: https://bugs.php.net/fix.php?id=62373&r=notwrong Not enough info: https://bugs.php.net/fix.php?id=62373&r=notenoughinfo Submitted twice: https://bugs.php.net/fix.php?id=62373&r=submittedtwice register_globals: https://bugs.php.net/fix.php?id=62373&r=globals PHP 4 support discontinued: https://bugs.php.net/fix.php?id=62373&r=php4 Daylight Savings: https://bugs.php.net/fix.php?id=62373&r=dst IIS Stability: https://bugs.php.net/fix.php?id=62373&r=isapi Install GNU Sed: https://bugs.php.net/fix.php?id=62373&r=gnused Floating point limitations: https://bugs.php.net/fix.php?id=62373&r=float No Zend Extensions: https://bugs.php.net/fix.php?id=62373&r=nozend MySQL Configuration Error: https://bugs.php.net/fix.php?id=62373&r=mysqlcfg