这种行为/实现有什么原因吗?
示例:
$array = array("index_of_an_array" => "value");
class Foo {
private $index_of_an_array;
function __construct() {}
}
$foo = new Foo();
$array = (array)$foo;
$key = str_replace("Foo", "", array_keys($array)[0]);
echo $array[$key];给我们一个完整的错误
注意到未定义的索引:在线编号9
例2:
echo date("Y\0/m/d");产出:
2016年
例如,! echo或var_dump()和其他一些函数将输出字符串“如实”,浏览器只隐藏\0字节。
$string = "index-of\0-an-array";
$strgin2 = "Y\0/m/d";
echo $string;
echo $string2;
var_dump($string);
var_dump($string2);产出:
数组索引 "Y/m/d“ 字符串(18)“一个数组的索引” 字符串(6) "Y/m/d“
请注意,$string长度为18,但显示了17个字符。
编辑
来自可能重复和php手册
键可以是整数,也可以是字符串。这个值可以是任何类型的。包含有效整数的字符串将转换为整数类型。例如,键" 8“实际上将存储在8下面。另一方面,"08”不会被转换,因为它不是有效的十进制整数。总之,任何字符串都可以是键。一个字符串可以包含任何二进制数据(最多2GB)。因此,键可以是任何二进制数据(因为字符串可以是任何二进制数据)。
来自php字符串详细信息
字符串可以组成的值没有任何限制;特别是,字符串中任何地方都允许值为0的字节(“NUL字节”)(但是,本手册中说的一些函数不属于“二进制安全”,可能会将字符串传递给库,这些库在NUL字节之后忽略数据。)
但是我仍然不明白为什么语言是这样设计的?这种行为/实现有什么原因吗?为什么PHP在任何地方都不把输入作为二进制安全处理,而只是在某些函数中处理?
来自评论
原因很简单,许多像
printf这样的PHP函数在幕后使用C库的实现,因为PHP开发人员很懒。
像echo,var_dump,print_r之类的不是吗?换句话说,输出某物的函数。如果我们看一下我的第一个例子,它们实际上是二进制安全的。对于我来说,为输出实现一些二进制安全和二进制不安全的函数是没有意义的。或者像C中的std那样使用一些函数,并编写一些全新的函数。
发布于 2016-05-03 14:44:59
对“为什么”的简短回答就是历史。
PHP最初是作为编写C函数的一种方式编写的,这样在生成HTML时就可以轻松地调用它们。因此,PHP字符串就是C字符串,它是一组任意字节。因此,在现代PHP术语中,我们会说没有任何东西是二进制安全的,仅仅是因为本来没有其他计划的。
早期的PHP并不打算成为一种新的编程语言,而是有机地发展起来,Lerdorf在回顾中指出:“我不知道如何阻止它,我从来没有打算编写一种编程语言…--我完全不知道如何编写一种编程语言,我只是在途中继续添加下一个逻辑步骤。”
随着时间的推移,语言越来越多地支持更精细的字符串处理功能,其中许多都考虑到了字符串的特定字节,并变得“二进制安全”。
至于字符串中的字节是如何转换为字符的,则未指定。虽然字符串的用户可能会选择将特殊的语义赋予具有
\0值的字节,但从PHP的角度来看,这些空字节没有特殊的意义。PHP不假定字符串包含任何特定数据,也不为任何字节或序列分配特殊值。
作为一种有机地发展起来的语言,还没有采取一种与C不同的普遍处理字符串的方式,因此函数和库是二进制安全的。
发布于 2016-05-03 12:26:56
PHP中的函数(在内部使用C字符串操作)在PHP术语中是“不二进制安全的”。C字符串是以字节0结尾的字节数组。当PHP函数在内部使用C字符串时,它逐个读取字符,当遇到字节0时,它将其视为字符串的结尾。字节0告诉C字符串函数哪里是字符串的结尾,因为C字符串不包含任何关于字符串长度的信息。
“非二进制安全”意味着,如果使用C字符串操作的函数以某种方式传递C字符串而不是以字节0结尾,则行为是不可预测的,因为函数将读取/写入字符串结束后的字节,向字符串和/或潜在崩溃的PHP添加垃圾。
例如,在C++中,我们有string对象。该对象还包含一个字符数组,但它也有一个length字段,在任何长度更改时都会更新该字段。因此,它不需要字节0来告诉它结束的位置。这就是为什么string对象可以包含任意数量的0字节,尽管这通常是无效的,因为它应该只包含有效的字符。
为了纠正这种情况,需要重写整个PHP核心,包括任何使用C字符串操作的模块,以便将“非二进制安全”函数发送到历史记录。这需要大量的工作,所有模块的创建者都需要为他们的模块生成新的代码。这可以在整个故事中引入新的bug和不稳定性。
字节0和“非二进制安全”函数的问题对于重新编写PHP和PHP模块代码并不那么重要。也许在一些较新的PHP版本中,有些东西需要从头开始编码,纠正这种情况是有意义的。
在此之前,您只需要知道,任何通过使用二进制安全函数将任意二进制数据放入字符串的数据都需要在末尾添加字节0。通常,当字符串末尾有意外的垃圾或PHP崩溃时,您会注意到这一点。
https://stackoverflow.com/questions/36933837
复制相似问题