Что в PHP означает бинарно-безопасная функция?


120

В PHPчем смысл существования функции binary-safe?

Что делает их особенными и где они обычно используются?

Ответы:


106

Это означает, что функция будет работать правильно, когда вы передадите ей произвольные двоичные данные (т.е. строки, содержащие байты, отличные от ASCII, и / или нулевые байты).

Например, небезопасная функция может быть основана на функции C, которая ожидает строки с завершающим нулем, поэтому, если строка содержит нулевой символ, функция проигнорирует все, что находится после него.

Это актуально, потому что PHP не разделяет чисто строковые и двоичные данные.


2
Означает ли это, что безопасные двоичные строки содержат только «символы» длиной 1 байт?
Чарли Паркер

3
@CharlieParker: Нет, ты понял это наоборот. Бинарная безопасность - это свойство функций, которое означает, что они правильно обрабатывают любую строку. Обратным будет строка, содержащая только символы ASCII и не содержащая нулевых символов - такая строка должна правильно обрабатываться любой функцией.
Майкл Боргвардт

возможно, я запутался, потому что читал протокол redis для «объемных строк», и в нем говорилось, что они представляют собой «единую двоичную безопасную строку». Думаю, теперь я правильно понял ваш пост. Однако имеет ли смысл говорить, что строка «бинарно безопасна» (как в приведенном мной примере)?
Чарли Паркер

93

Остальные пользователи уже упоминали, что binary safeозначает в целом.

В PHP значение более конкретное, ссылаясь только на то, что Майкл приводит в качестве примера.

Все строки в PHP имеют связанную длину, которая представляет собой количество байтов, составляющих их. Когда функция манипулирует строкой, она может:

  1. Положитесь на метаданные этой длины.
  2. Положитесь на то, что строка завершается нулем, т. Е. Что после данных, которые фактически являются частью строки, появится байт со значением 0.

Также верно и то, что все строковые переменные PHP, которыми манипулирует движок, также завершаются нулем. Проблема с функциями, которые полагаются на 2., заключается в том, что, если сама строка содержит байт со значением 0, функция, которая управляет ею, будет думать, что строка закончилась в этой точке, и проигнорирует все после этого.

Например, если бы strlenфункция PHP работала как стандартная библиотека C strlen, результат здесь был бы неверным:

$str = "abc\x00abc";
echo strlen($str); //gives 7, not 3!

15
Напоследок пример!
Raffaele

5
В моем тесте в PHP 7.0 функция strlen () является двоичной безопасной функцией.
linjie

@Artefacto: Вы говорите, что встроенная функция PHP strlen()является бинарно-безопасной функцией? Я подтверждаю это, потому что на странице руководства PHP для функции strlen()не упоминается, является ли это безопасной для двоичного кода функцией или небинарной безопасной функцией. Это единственное, чего не хватает в Руководстве по PHP, вызывает у меня замешательство, поэтому я хочу подтвердить это от вас. Я с нетерпением жду вашего ответа. Спасибо.
PHPLover

@PHPLover да strlen () безопасна для двоичного кода. запустить php -r 'var_dump("\x00\x00\x00");'для проверки, но php strlen был двоично безопасным в течение очень долгого времени, по крайней мере, начиная с php 4.x (при этом есть мерзость под названием "mb_overload", но давайте просто притворимся, что ее не существует - php.net /manual/en/mbstring.overload.php )
hanshenrik

62

Еще примеры:

<?php

    $string1 = "Hello";
    $string2 = "Hello\x00World";

    // This function is NOT ! binary safe
    echo strcoll($string1, $string2); // gives 0, strings are equal.

    // This function is binary safe
    echo strcmp($string1, $string2); // gives <0, $string1 is less than $string2.

?>

\xобозначает шестнадцатеричное представление. Смотрите: строки PHP

0x00 = NULL
0x04 = EOT (End of transmission)

Таблица ASCII для просмотра списка символов ASCII


Просто чтобы убедиться, что я понял, тогда это Hello\r\nWORLDне должно быть таким же, как Helloесли бы функция двоично-безопасная, верно?
Чарли Паркер

Также как реализована такая функция? Есть ли регулярное выражение, которое проверяет его бинарную безопасность, или оно использует другой метод?
Чарли Паркер

@Subscriberius: безопасна ли встроенная функция в strlen() двоичном коде ?
PHPNut
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.