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

Reply via email to