代码之家  ›  专栏  ›  技术社区  ›  PHPFan

哪些函数php被称为不“二进制安全”?这些“非二进制安全”函数向哪些库传递字符串?为什么呢?

  •  10
  • PHPFan  · 技术社区  · 7 年前

    我在用 Windows 10家庭单语言版 这是一个 64位操作系统 在我的机器上。

    我安装了最新版本的 XAMPP公司 已经安装 7.2.7菲律宾比索 在我的机器上。

    我是根据 PHP Manual 以下内容:

    这个 一串 在PHP中,实现为一个字节数组和一个整数 指示缓冲区的长度。它没有关于如何 这些字节转换为字符,将任务留给 程序员。字符串的值没有限制 由组成;尤其是值为0(nul bytes)的字节 允许在字符串中的任何位置(不过,这里说的是一些函数 手册不是二进制安全的,可以将字符串交给库 忽略nul字节后的数据。)

    我非常了解PHP中二进制安全函数和非二进制安全函数之间的区别。我心里一直在怀疑。请逐一回答,并附上适当的解释和适当的例子。

    • 在PHP中出现“非二进制安全”和“二进制安全”函数的现象仅仅是因为整个PHP解析器都是用 C语言 是吗?
    • 在处理包含任何值(包括nul byte)的字符串时,C和PHP之间有什么区别?
    • 我想要PHP中“非二进制安全”和“二进制安全”的完整函数列表。
    • “非二进制安全”和“二进制安全”的特性是否仅适用于通过字符串操作的函数,而不适用于处理PHP中其他类型的PHP函数?
    • 为什么非二进制安全函数会将字符串传递给库?
    • 非二进制安全函数是否仅在处理的字符串包含nul byte时才将字符串传递给库?
    • 这些“非二进制安全”函数向哪些库传递字符串?
    • 这些库如何处理从“非二进制安全”函数接收的字符串?
    • 在将包含nul byte的字符串交给某个库之后,“非二进制安全”函数是否像“二进制安全”函数那样工作?
    3 回复  |  直到 7 年前
        1
  •  9
  •   LBear    7 年前

    正如阿卡沙解释的那样,“二进制安全”和“非二进制安全”的问题与语言无关。

    使用一个空字节(0x00)来表示字符串的结尾比较简单(这可能就是C使用它的原因)。 但缺点是字符串中的任何地方都不能有空字节 如果您必须能够处理各种数据,这是一个很大的限制。 将长度存储为字符串的元数据部分更为复杂,如pete所示,但它允许您处理任何类型的数据。

    关于哪些函数是“二进制安全”或“非二进制安全”, 只需阅读PHP手册 之前 使用函数。 我就是这么做的。 不需要构建一个列表,因为PHP手册已经解释了您需要了解哪些函数,包括它们是否是二进制安全的。

    我相信,你的大部分文章都是因为对你引用的PHP手册的解释有误解,特别是这部分:

    但是,本手册中说不安全的一些函数可能会将字符串交给忽略nul字节后数据的库。

    让我试着通过添加一些我自己的词来更清楚地表达:

    但是,本手册中说的一些函数不是二进制安全的, 功能是否 可以将字符串传递给忽略nul字节后数据的库。

    所以它并没有说“非二进制安全函数将字符串交给库”,这是一种误解。 它的意思是“可以将字符串传递给忽略nul字节后数据的库的函数,在本手册中称为不二进制安全的函数”。

    “移交给图书馆”只是“从其他图书馆调用函数”的另一种说法。 “忽略nul字节后的数据”是一种称为非二进制安全的行为。

    另一种说法是:

    本手册中的一些功能被称为“二进制安全”。 因为 它们可以调用其他不“二进制安全”的函数(忽略nul字节后数据的函数)。

    我希望这能帮你清理干净。

        2
  •  5
  •   Pieter van den Ham    7 年前

    传统上,有两种表示字符串的方法:使用特殊字符发送字符串结尾的信号,或将字符串长度与字符串数据一起存储。C使用前者;字符串是以空字符结尾的字符数组。但是,这有一个限制,即C中的字符串不能在任何其他地方使用空字符,只能在末尾使用空字符。

    为了克服这个限制,PHP引擎使用这个结构来表示字符串:

    struct _zend_string {
        zend_refcounted_h gc; /* refcount struct */
        zend_ulong        h;  /* hash value */
        size_t            len; /* length of string */
        char              val[1]; /* array of chars (using struct "hack") */
    };
    

    如您所见,php开发人员选择存储字符串的长度及其数据。

    现在,如果混合使用“二进制安全”和“非二进制安全”功能,会发生什么?

    考虑在编写PHP扩展时可能使用的以下C代码:

    zend_string *a = zend_string_init("a\0b", /* string length */ 3, 0);
    zend_string *b = zend_string_init("a\0c", /* string length */ 3, 0);
    
    if (strcmp(a->val, b->val) == 0) {
        php_printf("Strings are equal!");
    }
    

    你认为会发生什么?此代码输出“字符串相等!”但他们显然不平等。自 strcmp 不考虑字符串的长度,它是一个非二进制安全函数。

    大多数C的标准库字符串函数都可以被归类为“非二进制安全”函数,因为它依赖于空终止字符。

    处理时 zend_string 在扩展代码中,应该使用zend字符串函数( zend_string_* )而不是C的字符串库。

    要修复以前的代码:

    if (zend_string_equals(a, b)) {
        php_printf("Equal!");
    } else {
        php_printf("Not equal");
    }
    

    现在正确打印“不相等”。

        3
  •  3
  •   arkascha    7 年前

    函数是否以“二进制安全”的方式处理运行时数据的问题与系统所使用的语言无关。这是一个如何处理数据的问题。PHP是一种高级语言,这意味着它具有字符串类型的高级实现。这不依赖于C所依赖的终止空字符,而是字符串类型维护有关存储字符串的元数据,这使得实现更加灵活和可靠。然而,这与是否“二进制安全”几乎没有关系。

    你的其他观点不能得到明确的回答。PHP使用的库取决于您的设置,即动态环境。潜在的库如何处理移交给它们的数据与PHP函数是否可以被视为“二进制安全”没有任何关系——库不知道PHP,它只得到移交的数据,并根据库的实现方式处理这些数据。

    推荐文章