7

PHP 7.4 的向后不兼容更改列表包含以下注释

序列化

o 序列化格式已被删除。由于它从未由 PHP 生成,因此这可能只会破坏手动制作的字符串的反序列化。

(请注意,这是指用于对象序列化的小格式o,而不是大格式。)O

似乎这从未由 PHP 的serialize()函数生成,但该注释存在的事实意味着它已被unserialize()函数识别。

我做了一个小测试小提琴 (3v4l.org),这表明这不仅仅是 big- 的同义词O,这将是一个明显的可能性。

小提琴通过输出的错误消息中的差异公开了 PHP 中的更改。在 PHP >= 7.4 中,我们在位置 0(o遇到 的位置)出现错误,而在 7.4 之前,错误在位置 5(数据所在的位置)报告。这意味着它o已被识别,但数据格式错误,这与我上面已经推断的内容相关。

那么,o序列化格式是什么,它反序列化为什么,如果 PHP 本身没有实际生成它,为什么它支持这样的特性?

4

1 回答 1

15

最初,PHP 3 用于o:<num_fields>:{<fields>}序列化对象。

以下程序适用于 PHP 4.0.0,可以从php.net/releases/index.php下载(Windows 二进制文件仍然适用于 Windows 10!):

<?php

var_dump(unserialize('o:0:{}'));

输出:

X-Powered-By: PHP/4.0.0
Content-type: text/html

object(stdClass)(0) {
}

我能够将对象序列化格式的原始实现追溯到1999 年的此提交。请参阅php3api_var_serialize

那年晚些时候,对象序列化格式更改为包含正在序列化的对象的类名,为 PHP 4 做准备。这次提交将序列化格式更改为o:<classname_length>:"<class_name>":<num_fields>:{<fields>}

这使得 PHP3 和 PHP4 的输出不兼容:PHP4 将无法反序列化使用 PHP3 序列化的对象。因此,添加了另一个提交,更改oO(小写 o 到大写 O)。 o仍然支持unserialize()反序列化使用 PHP3 序列化的对象,但serialize()不再使用o

2000年,序列化/反序列化代码被重构,产生了我们今天看到的文件

可能发生的情况是兼容性层在此过程中的某个地方出现了问题,没有人足够关心 PHP3 的兼容性来修复它。开头的代码不再适用于过去 15 年发布的任何 PHP 版本。

于 2020-12-29T23:53:44.707 回答