一个神奇的PHP反序列化报错的问题 unserialize(): Error at offset 3

Notice:  unserialize(): Error at offset 34 of 1045 bytes。

第34的字符是红色的这段: a:2:{i:233;a:1:{i:155048525529123;a:5:{s:21:"private....

原因是php运行在32位系统上,数字索引超过了数字范围导致的。。

也就是反序列化时整形数据溢出导致的,可以使用如下函数得到能正常使用的返回值:


function _unserialize($string)
{

    $string = preg_replace_callback('#i:(\d{11,20});#s',function($match){return 's:'.strlen($match[1]).':"'.$match[1].'";';},$string);
    return unserialize($string );
}



原理是把所有超过10位的数字转换成字符串。

根据PHP官方手册所说,整型数的字长和平台有关,尽管通常最大值是大约二十亿(32 位有符号)。64 位平台下的最大值通常是大约 9E18。PHP 不支持无符号整数。Integer 值的字长可以用常量 PHP_INT_SIZE来表示,自 PHP 4.4.0 和 PHP 5.0.5后,最大值可以用常量 PHP_INT_MAX 来表示。


但是,当我们在Windows下使用64位PHP的时候,PHP_INT_SIZE为4,PHP_INT_MAX为2^31-1。与之相反的是,如果在Linux下使用64位PHP,PHP_INT_SIZE为8,PHP_INT_MAX为2^63-1。PHP Bugs官方也有这么一条BUG报告:https://bugs.php.net/bug.php?id=64863

有话要说