PHP从64位到32位的非序列化整数

时间:2011-10-26 14:43:47

标签: php serialization architecture integer-overflow

我一直在尝试在32位服务器上反序列化在64位服务器上序列化的对象。我已将我的问题隔离到对象中的整数。这是对问题的一个小小的再现。

在64位计算机上:

$i = serialize('20110510134021'); //i:20110510134021;

在32位计算机上:

$i = unserialize('i:20110510134021;');

给出错误

Notice: unserialize(): Error at offset 0 of 16 bytes

现在我明白这些序列化方法不应该用于跨系统数据传输。但是,我们只是尝试将数据迁移到另一个系统,而不是主动用于传输。这是一次性事情。

我认为这可能是由于整数溢出,但即使在32位服务器上,我也可以做类似的事情

$i = 20110510134021;
echo $i;

它会正常工作。我猜测PHP整数类型可以缩放到某种双重类型或类似的东西。但是当它反序列化时为什么不这样做呢?

如何反序列化这些对象?如果我不能,有没有办法将它们转换成其他东西?最后,有没有人在PHP本身编写反序列化方法?或者有协议的细节?我可以使用它并为这些整数设置一个自定义的案例。

感谢。

注意:我无法访问原始数据,只能访问序列化结果。

3 个答案:

答案 0 :(得分:2)

32位系统的最大整数为4294967296; $i = 20110510134021;有效,因为PHP将变量转换为double。

所以用i

替换d
$i = unserialize('d:20110510134021;');

如果运行此脚本,您将在正在运行的系统上看到变量的正确表示(d:在32位系统上,i:在64位系统上):

$int = 20110510134021;
var_dump(serialize($int));

答案 1 :(得分:1)

简单的解决方案是,如果您知道在32位机器上序列化的数据有可能在32位机器上被反序列化,那么在序列化之前将其转换为(double)。

然后它将被反序列化为double,为每个整数提供比每个整数(32位)标准4字节更多的位

一旦反序列化,只需使用该数字作为双精度。在99%的情况下,这是一个很好的解决方案。对于非常大的数字,在32位机器上分配给数字上的“真实”部分的位数仍然是不够的。我认为它是56位,所以最大整数仍然明显大于int类型的32位。

答案 2 :(得分:1)

怎么样:

$serialized = 'i:20110510134021';

if (preg_match('/i\:([\d]+)/', $serialized, $match))
{
    $unserialized = $match[1];
}