preg_replace & preg_replace_callback проблемы безопасности - PullRequest
0 голосов
/ 19 октября 2011

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

Итак, наши страницы хранятся в БД, и когда они отображаются в нашем шаблоне, мы в настоящее время используем три разные функции preg_replace с модификаторами e на всей html-странице.

Это кажется медленным, поэтому я хотел бы изменить его на использование только одного вызова preg_replace и иметь возможность предоставлять пользовательскую функцию с 1 аргументом способом bbcode: Пример:

[FUNC: testfunc (тестовая строка)]

Итак, это то, что я придумал ... Я не уверен, какой метод более безопасен, preg_rplace с e modifer или preg_replace_callback:

<?php
$str = '
<h2>Title That should Not Be Affected</h2>
<p>[FUNC:linkbox(/somestuff/newpage.html)]</p>
<a href="[FUNC:getvar(url)]">[FUNC:getvar(title)]</a>
<p>Random Html THat should not be affected</p>
<p>[FUNC:linkbox(/somestuff/otherpage.html)]</p>
';

$str2 = preg_replace_callback('~\[FUNC:(.*?)\((.*?)\)\]~', 'callback_caller', $str);

$str = preg_replace('~\[FUNC:(.*?)\((.*?)\)\]~e', 'emodcaller("\\1", "\\2")', $str);

echo $str.'<br><br>'.$str2;

function callback_caller($args){

    if(!isset($args[0], $args[1]))
        return false;

    $func = strip_tags($args[1]);
    $param = isset($args[2]) ? strip_tags($args[2]) : '';

    //Only allow calling of known functions
    switch($func){

        case 'linkbox':
            return linkbox($param);
        break;

        case 'getvar':
            return getvar($param);
        break;

        case 'default':
            return '';
        break;

    }

}

function emodcaller($fun, $arg){
    $arg = strip_tags($arg);

    //Only allow calling of known functions
    switch($fun){
        case 'linkbox':
            return linkbox($arg);
        break;

        case 'getvar':
            return getvar($arg);
        break;

        case 'default':
            return '';
        break;

    }

}

function linkbox($addy){
    return 'Linkbox Called: '.$addy;
}

function getvar($arg) {

    switch($arg){
        case 'url':
            return '/index.html';
        break;

        case 'title':
            return 'This is a test title';
        break;
    }

}
?>

Что мне нравится в использовании модификатора e, так это то, что я могу добавить другой параметр к вызову функции непосредственно в php, если мне нужно, например:

preg_replace('~\[FUNC:(.*?)\((.*?)\)\]~e', 'emodcaller("\\1", "\\2", $page->getid())', $str);

Один метод безопаснее другого? Они оба огромные угрозы безопасности? Я должен иметь некоторую реализацию этих ..

Редактировать: я понял, что вы можете передать функции обратного вызова дополнительные параметры, используя анонимную функцию, такую ​​как:

$content = preg_replace_callback(
'~(?:\<p\>)?\[FUNC:(.*?)\((.*?)\)\](?:\<\/p\>)?~',
function($matches) use ($article) {
return callback_caller($matches, $article);
}, 
$content);

Это передает функции callback_caller () весь мой класс статьи для использования. Является ли создание анонимной функции для каждого совпадения плохим с точки зрения производительности?

1 Ответ

1 голос
/ 19 октября 2011

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

Вы всегда можете использовать вызов метода для обратного вызова, например:

$content = preg_replace_callback($rx, array($obj, 'method_name'), $content);

Это позволяет избежать необходимости передавать какие-либо аргументы в метод, если они уже являются свойствами объекта.

Я склонен отдавать предпочтение preg_replace_callback() над preg_replace() с 'e', ​​потому что это позволяет избежать ловушек правильного экранирования любых совпадений с образцом в коде eval'd и избежать дополнительных затрат на необходимость оценки вообще (и если вы Вы используете кэш кода операции, такой как APC, это означает, что компиляция нуля по сравнению с eval, которая компилируется при каждом вызове). Это также делает код немного легче для чтения - eval'd код всегда выглядит немного уродливее, потому что вы должны экранировать строку.

Тем не менее, нет ничего изначально неправильного в использовании preg_replace () с 'e'.

...