PHP 的 "o" 序列化格式有什么用?
What was PHP's "o" serialization format for?
PHP 7.4 的向后不兼容更改列表包含 the following note:
Serialization
The o serialization format has been removed. As it is never produced by PHP, this may only break unserialization of manually crafted strings.
(请注意,这里指的是 little-o
,而不是用于对象序列化的 big-O
格式。)
这似乎从未由 PHP 的 serialize()
函数生成,但该注释存在的事实表明它 被 识别unserialize()
函数。
我做了 little test fiddle (3v4l.org) 这表明这不仅仅是 big-O
的同义词,它将是一种明显的可能性。
fiddle 通过输出的错误消息的差异公开了 PHP 中的更改。在 PHP >= 7.4 中,我们在位置 0(遇到 o
的地方)出现错误,而在 7.4 之前,错误报告在位置 5(数据所在的位置)。这意味着 o
已被识别,但数据格式错误,这与我在上面已经推断出的内容有关。
那么,什么是 o
序列化格式,它反序列化成什么,如果 PHP 本身并没有实际生成它,为什么要支持这样的功能?
最初,PHP3使用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 年 this commit 对象序列化格式的原始实现。
参见 php3api_var_serialize。
那年晚些时候,对象序列化格式为 changed 以包含正在序列化的对象的类名,为 PHP 4 做准备。
此提交将序列化格式更改为 o:<classname_length>:"<class_name>":<num_fields>:{<fields>}
这使得 PHP3 和 PHP4 的输出不兼容:PHP4 将无法反序列化使用 PHP3 序列化的对象。
因此,another commit was added 将 o
更改为 O
(小写 o 变为大写 O)。
o
仍受 unserialize()
支持以反序列化使用 PHP3 序列化的对象,但 serialize()
不再使用 o
。
2000 年,serialization/unserialization 代码 was refactored, resulting in the file we see today。
可能发生的事情是兼容性层在某个地方坏了,没有人足够关心 PHP3 兼容性来修复它。
开头的代码不再适用于过去 15 年发布的任何 PHP 版本。
PHP 7.4 的向后不兼容更改列表包含 the following note:
Serialization
The o serialization format has been removed. As it is never produced by PHP, this may only break unserialization of manually crafted strings.
(请注意,这里指的是 little-o
,而不是用于对象序列化的 big-O
格式。)
这似乎从未由 PHP 的 serialize()
函数生成,但该注释存在的事实表明它 被 识别unserialize()
函数。
我做了 little test fiddle (3v4l.org) 这表明这不仅仅是 big-O
的同义词,它将是一种明显的可能性。
fiddle 通过输出的错误消息的差异公开了 PHP 中的更改。在 PHP >= 7.4 中,我们在位置 0(遇到 o
的地方)出现错误,而在 7.4 之前,错误报告在位置 5(数据所在的位置)。这意味着 o
已被识别,但数据格式错误,这与我在上面已经推断出的内容有关。
那么,什么是 o
序列化格式,它反序列化成什么,如果 PHP 本身并没有实际生成它,为什么要支持这样的功能?
最初,PHP3使用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 年 this commit 对象序列化格式的原始实现。 参见 php3api_var_serialize。
那年晚些时候,对象序列化格式为 changed 以包含正在序列化的对象的类名,为 PHP 4 做准备。
此提交将序列化格式更改为 o:<classname_length>:"<class_name>":<num_fields>:{<fields>}
这使得 PHP3 和 PHP4 的输出不兼容:PHP4 将无法反序列化使用 PHP3 序列化的对象。
因此,another commit was added 将 o
更改为 O
(小写 o 变为大写 O)。
o
仍受 unserialize()
支持以反序列化使用 PHP3 序列化的对象,但 serialize()
不再使用 o
。
2000 年,serialization/unserialization 代码 was refactored, resulting in the file we see today。
可能发生的事情是兼容性层在某个地方坏了,没有人足够关心 PHP3 兼容性来修复它。 开头的代码不再适用于过去 15 年发布的任何 PHP 版本。