str_replace () на многобайтовых строках опасно? - PullRequest
22 голосов
/ 24 сентября 2010

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

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

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

Есть ли простой способ решить эту проблему, или янеправильное понимание проблемы?

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

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

Ответы [ 4 ]

27 голосов
/ 24 сентября 2010

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

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

Edit Вот реализация 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;
}

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

5 голосов
/ 17 января 2011

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

3 голосов
/ 24 сентября 2010

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

0 голосов
/ 24 сентября 2010

Из того, что я понимаю, большая часть этого типа вставки строк решается с помощью mysql_real_escape_string ();функция.

http://php.net/manual/en/function.mysql-real-escape-string.php

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...