Подтвердить что ты не робот

Str_replace() на многобайтовых строках опасно?

Учитывая некоторые многобайтовые наборы символов, могу ли я предположить, что следующее не делает то, что оно предназначалось?

$string = str_replace('"', '\\"', $string);

В частности, если вход был в наборе символов, который может иметь допустимый символ, такой как 0xbf5c, так что злоумышленник может ввести 0xbf22, чтобы получить 0xbf5c22, оставив действительный символ, за которым следует некорректная двойная кавычка (").

Есть ли простой способ смягчить эту проблему, или я вообще не понимаю проблему?

(В моем случае строка входит в атрибут value входного тега HTML: echo 'input type = "text" value = "'. $string. '" > ';)

EDIT: В этом отношении, как насчет функции, такой как preg_quote()? Для этого нет аргументов для набора символов, поэтому в этом сценарии кажется совершенно бесполезным. Если у вас нет возможности ограничить кодировку UTF-8 (да, это было бы хорошо), похоже, что вы действительно инвалид. Какие функции замены и кавычки доступны в этом случае?

4b9b3361

Ответ 1

Нет, вы правы: использование однобайтовой строковой функции в многобайтовой строке может привести к неожиданному результату. Вместо этого используйте функции многобайтовых строк, например mb_ereg_replace или mb_split:

$string = mb_ereg_replace('"', '\\"', $string);
$string = implode('\\"', mb_split('"', $string));

Изменить. Речь идет о реализации mb_replace с использованием варианта split-join:

function mb_replace($search, $replace, $subject, &$count=0) {
    if (!is_array($search) && is_array($replace)) {
        return false;
    }
    if (is_array($subject)) {
        // call mb_replace for each single string in $subject
        foreach ($subject as &$string) {
            $string = &mb_replace($search, $replace, $string, $c);
            $count += $c;
        }
    } elseif (is_array($search)) {
        if (!is_array($replace)) {
            foreach ($search as &$string) {
                $subject = mb_replace($string, $replace, $subject, $c);
                $count += $c;
            }
        } else {
            $n = max(count($search), count($replace));
            while ($n--) {
                $subject = mb_replace(current($search), current($replace), $subject, $c);
                $count += $c;
                next($search);
                next($replace);
            }
        }
    } else {
        $parts = mb_split(preg_quote($search), $subject);
        $count = count($parts)-1;
        $subject = implode($replace, $parts);
    }
    return $subject;
}

Что касается комбинации параметров, эта функция должна вести себя как singlebyte str_replace.

Ответ 2

Код совершенно безопасен с разумными мультибайтными кодировками, такими как UTF-8 и EUC-TW, но опасными с сломанными такими, как Shift_JIS, GB * и т.д. Скорее чем пройти всю головную боль и накладные расходы, чтобы быть в безопасности с этими устаревшими кодировками, я бы рекомендовал просто поддерживать только UTF-8.

Ответ 3

Вы можете использовать либо mb_ereg_replace, сначала указав кодировку с помощью mb_regex_encoding(). Альтернативно, если вы используете UTF-8, вы можете использовать preg_replace с модификатором u.