Jump to content
  • 0

Подводные камни eval()


Vialls
 Share

Question

Очень много раз слышал, что не рекомендуется использовать функцию eval() из за ее опасности. У меня щас, как раз такая ситуация, когда её необходимо использовать... С чем я могу столкнуться, как предостеречься?

Link to comment
Share on other sites

22 answers to this question

Recommended Posts

  • 0

Нужно быть осторожным со строкой которую передаете в evil.

Если исполнять переменную из GET или POST переменных, то есть вариант запуска эксплоитов.

Вообще в ней нет ничего опасного - функция как функция :unsure:

Link to comment
Share on other sites

  • 0
Да, например call_user_func или $$varible или $class = new $class_name(); ...

Опиши проблему, может мы подскажем пути решения?

Опс, я запоздал :unsure:

Не опоздал, я предыдущее сообщение запорол :)

В общем требуется следующее. Допустим есть файл:

...
{print $values['bla_bla'];} - вместо этого должно выводить значение глобальной переменной $value['bla_bla']
{parse $values;} - обходит все элемента массива $values и выводит их
...

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

function parse($template)
{
global $values;
// .... идет обработка всего
eval('?>'.$template);
}

Примерно так.

Link to comment
Share on other sites

  • 0

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

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

... {print $val} то ищешь сначала символ {. Нашел - значит тут есть команда. Смотришь что после него, ага - команда print, значит печатать чтото будем... ну и так далее. Вот в очень примитивном варианте, мне кажется, можно все это на строковых функциях организовать. Ну и регулярных выражениях, в качестве пушки для воробьев, хотя их рекомендуют использовать только там, где строковыми ф-циями не обойтись, ибо работают существенно медленнее.

Вот, ну дальше понятно дело, встанет вопрос - как вызвать ф-цию, имя которой заданно строковой переменной, обратиться к методу класса, или обратиться к переменной.

Вызвать метод класса или просто ф-цию можно используя ф-цию call_user_func, как выше верно было сказано (кстати на удивление часто встречаю последнее время этот вопрос, видать все ринулись свои шаблонизаторы писать : ))) ). Как к переменной обратиться, имя которой строкой задано, с ходу чегото не лезет в голову, ща попробую сообразить...

Ну и еще можно посмотреть как Smarty парсит шаблоны, там именно эта задача решена, хотя подозреваю что курить код Смарти не легче чем свой написать : ))

А ну собственно выше верно сказали:

$var = 'qq';

$tmp = 'var';

echo $$tmp;

Link to comment
Share on other sites

  • 0
Я вообще не специалист по шаблонизаторам, могу лишь руками в воздухе помахать, но все же помахаю, может что умное выйдет...

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

... {print $val} то ищешь сначала символ {. Нашел - значит тут есть команда. Смотришь что после него, ага - команда print, значит печатать чтото будем... ну и так далее. Вот в очень примитивном варианте, мне кажется, можно все это на строковых функциях организовать. Ну и регулярных выражениях, в качестве пушки для воробьев, хотя их рекомендуют использовать только там, где строковыми ф-циями не обойтись, ибо работают существенно медленнее.

Вот, ну дальше понятно дело, встанет вопрос - как вызвать ф-цию, имя которой заданно строковой переменной, обратиться к методу класса, или обратиться к переменной.

Вызвать метод класса или просто ф-цию можно используя ф-цию call_user_func, как выше верно было сказано (кстати на удивление часто встречаю последнее время этот вопрос, видать все ринулись свои шаблонизаторы писать : ))) ). Как к переменной обратиться, имя которой строкой задано, с ходу чегото не лезет в голову, ща попробую сообразить...

Ну и еще можно посмотреть как Smarty парсит шаблоны, там именно эта задача решена, хотя подозреваю что курить код Смарти не легче чем свой написать : ))

А ну собственно выше верно сказали:

$var = 'qq';

$tmp = 'var';

echo $$tmp;

Т.е. вы имеете ввиду сделать так. Парсим документ, пока не встречается "{" || "}" все выводим. Далее как встречается эта конструкция ({ }), мы начинаем обрабатывать ее вызывать функции и т.д. Конструкция заканчивается и мы дальше все выводим, до следующей конструкции?

Link to comment
Share on other sites

  • 0

Vialls, ухум. Я бы начал реализовывать с этого. И наверно можно на ты :unsure: Не люблю в виртуальном мире общение на "вы", есть хорошее изречение на эту тему:

Когда в виртуале переходят на "вы" в реале уже бьют морду.

Если время терпит могу попытаться посмотреть, как делает Смарти, просто врядли это можно понять с ходу глянув, там наверняка сложная система, но зато наверняка и оптимальная.

Link to comment
Share on other sites

  • 0

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

Link to comment
Share on other sites

  • 0
Vialls, ухум. Я бы начал реализовывать с этого. И наверно можно на ты :unsure: Не люблю в виртуальном мире общение на "вы", есть хорошее изречение на эту тему:

Когда в виртуале переходят на "вы" в реале уже бьют морду.

Если время терпит могу попытаться посмотреть, как делает Смарти, просто врядли это можно понять с ходу глянув, там наверняка сложная система, но зато наверняка и оптимальная.

Я тоже думал о таком варианте. Наверно так и сделаю. Если ничего в голову не придет. Спасибо.

Второй вариант у меня немного другой, с eval(), т.е. тоже парсишь документ, а потом на месте "{}", вставляем PHP код (эквивалент, того, что было между {}), ну а далее обрабатываем это все eval(). Кстати smarty(), работает примерно таким-же образом, вроде. Он при первой обработке шаблона, создает файлы, со вставками PHP кода, вместо того, что было между {}. А потом при вызове метода display(), он наверно просто подключает этот файл и все...

P.S.

Окей, будем на "ты"

Link to comment
Share on other sites

  • 0

Да, именно так Смарти и делает. Т.е. у него 2 этапа, первый - парсинг текста шаблона и создание пхп-кода с echo-ми, а второй - подключение этого файла. Но евал-ов там никаких нет, наверное за исключением его личного тега {php}, который в одной книжке назван "абсолютным злом".

Вообще, если ты в шаблоне пишешь чистый пхп-код, который собираешься евалить, то зачем собственно? Можно сразу писать пхп внутрь хтмл:

<html>

теги теги теги...

<?php

код код код...

?>

теги теги теги...

Или все-таки подразумеваются некие служебные команды, ну как в Смарти {$varible}

Link to comment
Share on other sites

  • 0

Наверно сделаю-ка я, как Smarty. Буду подгружать код во временный файл, и include()-ить его... Хотя попробую двумя способами сразу, твоим, и как у Smarty()... Потестю на быстродействие, и отпишусь: )

Link to comment
Share on other sites

  • 0

Кстате, уже забыл про эту тему, давно сделал. Способ, который описал Dima_2015 в моем случае работает немного быстрее, чес способ с подгрузкой в файл и include() его. Но если писать именно шаблонизатор (не мой случай), то быстрее работает подгрузка PHP файла, т.к. не нужно каждый раз обрабатывать шаблон, а достаточно обработать один раз (после его редактирования)...

Link to comment
Share on other sites

  • 0

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

в документации сказано:eval() вычисляет строку, заданную в code_str, как код PHP. Помимо всего прочего, это может оказаться полезным для хранения кода в текстовом поле БД для последующего исполнения.

не совсем понятно, что она всё таки делает ещё был приведён такой пример

<?php
$string = 'cup';
$name = 'coffee';
$str = 'This is a $string with my $name in it.<br>';
echo $str;
eval ("\$str = \"$str\";");
echo $str;
?>

и сказанно, что он выводит: This is a $string with my $name in it.

This is a cup with my coffee in it.

Хотелось бы узнать для чего же придумали эту функцию и как, и где она используется?

P.S извиняюсь за глупый вопрос не по теме.

Edited by Игорь Ермаков
Link to comment
Share on other sites

  • 0

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

<?php
$phpcode = "<?php echo '12345'; ?>";
eval("?>".$phpcode);
?>

Этот код выведет 12345.

Т.е. если бы ты сделал так:

<?php
$phpcode = "<?php echo '12345'; ?>";
echo $phpcode;
?>

то вывело бы <?php echo '12345'; ?>, а не 12345...

Удобно если например у тебя лежит в БД код, ты его от туда выдераешь, в функцию eval пускаешь, и она его выполняет...

Edited by Vialls
Link to comment
Share on other sites

  • 0

всё понятно спасибо!

только меня смущает одна вещь

в строке eval("?>".$phpcode);

для чего здесь эта ?>

в мануале синтаксис этой функции вообще показывается как eval ("\$str = \"$str\";");

не понятно, что обозначают эти слеши, или вот это: ?>

Link to comment
Share on other sites

  • 0

Просто в переменной $phpcode, код начинается с <?php, а функция eval не закрывает предыдущий тег, и если бы не было ?>, то получилось бы так:

<?php
$phpcode = "<?php echo '12345'; ?>";
<?php echo '12345'; ?><?php
?>

А с ?>, вот так:

<?php
$phpcode = "<?php echo '12345'; ?>";
?><?php echo '12345'; ?><?php
?>

Link to comment
Share on other sites

  • 0

немного поэксперементировал с этой штукой, вроде понял зачем этот знак ?>

только я не понял зачем вы написали

<?php

$phpcode = "<?php echo '12345'; ?>";

?><?php echo '12345'; ?><?php

?>

не понимаю зачем окончание здесь, я его обрезал и ничего не изменилось всё работает.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy