За все годы разработки php я всегда слышал, что использование eval()
- зло.
Учитывая следующий код, не имеет ли смысла использовать второй (и более элегантный) вариант? Если нет, то почему?
// $type is the result of an SQL statement
// e.g. SHOW COLUMNS FROM a_table LIKE 'a_column';
// hence you can be pretty sure about the consistency
// of your string
$type = "enum('a','b','c')";
// possibility one
$type_1 = preg_replace('#^enum\s*\(\s*\'|\'\s*\)\s*$#', '', $type);
$result = preg_split('#\'\s*,\s*\'#', $type_1);
// possibility two
eval('$result = '.preg_replace('#^enum#','array', $type).';');
$result = array(); preg_replace_callback('#^enum\s*\(\s*\'|\'\s*\)\s*$#', function($m) use($result) { $result[] = $m[1]; }, $type);
Ответы:
Я бы с осторожностью назвал eval () чистым злом. Динамическая оценка - мощный инструмент, который иногда может спасти жизнь. С eval () можно обойти недостатки PHP (см. Ниже).
Основные проблемы с eval ():
Основная проблема с фактическим использованием eval () только одна:
Как правило, я придерживаюсь следующего:
источник
eval является злом, когда существует лишь малейшая вероятность того, что ввод пользователя будет включен в вычисляемую строку. Когда вы выполняете eval без содержимого, полученного от пользователя, вы должны быть в безопасности.
Тем не менее, вы должны подумать как минимум дважды, прежде чем использовать eval, это выглядит обманчиво простым, но с обработкой ошибок (см. Комментарий VBAssassins), возможностью отладки и т. Д. Это уже не так просто.
Итак, практическое правило: забудьте об этом. Когда eval - это ответ, вы, вероятно, задаете неправильный вопрос! ;-)
источник
eval()
невозможно, это лучший подход. Многие говорят,eval()
что в некоторых случаях это неизбежно, но они не приводят никаких конкретных примеров, которые мы могли бы спорить - таким образом, эта дискуссия не имеет смысла. Так что, люди, которые говорят, чтоeval()
это неизбежно, сначала докажите это!eval всегда одинаково "злой".
Если вы считаете eval () злом, это всегда зло. Он не теряет магической злобы в зависимости от контекста.
На мой взгляд, вопрос «когда eval () не является злом?» похоже, подразумевает, что недостатки использования eval () волшебным образом исчезают в некоторых контекстах.
Использование eval (), как правило, является плохой идеей, потому что оно снижает читаемость кода, способность предсказывать путь кода (и возможные последствия этого для безопасности) до выполнения и, следовательно, ухудшает способность анализировать и отлаживать код. Использование eval () также может предотвратить оптимизацию оцениваемого кода и окружающего его кода с помощью кеша опкодов, такого как Zend Opcache, интегрированного в PHP 5.5 и выше, или JIT-компилятором, например, в HHVM.
Более того, нет ситуации, в которой абсолютно необходимо использовать eval () - PHP - это полноценный язык программирования без него. Для чего бы вы ни хотели использовать eval (), это еще один способ сделать это.
Считаете ли вы это злом или можете лично оправдать использование eval () в некоторых случаях, зависит от вас. Для некоторых зло слишком велико, чтобы его оправдать, а для других eval () - удобный ярлык.
источник
В этом случае eval, вероятно, достаточно безопасен, поскольку пользователь никогда не сможет создать произвольные столбцы в таблице.
Хотя это не совсем элегантно. В основном это проблема парсинга текста, и злоупотребление парсером PHP для обработки кажется немного взломанным. Если вы хотите злоупотребить языковыми функциями, почему бы не злоупотребить парсером JSON? По крайней мере, с парсером JSON нет никакой возможности внедрения кода.
$json = str_replace(array( 'enum', '(', ')', "'"), array) '', '[', ']', "'"), $type); $result = json_decode($json);
Регулярное выражение, вероятно, является наиболее очевидным способом. Вы можете использовать одно регулярное выражение для извлечения всех значений из этой строки:
$extract_regex = '/ (?<=,|enum\() # Match strings that follow either a comma, or the string "enum("... \' # ...then the opening quote mark... (.*?) # ...and capture anything... \' # ...up to the closing quote mark... /x'; preg_match_all($extract_regex, $type, $matches); $result = $matches[1];
источник
eval()
медленно, но я бы не назвал это злом.Это плохое использование, которое мы делаем, что может привести к инъекции кода и быть злом.
Простой пример:
$_GET = 'echo 5 + 5 * 2;'; eval($_GET); // 15
Вредный пример:
$_GET = 'system("reboot");'; eval($_GET); // oops
Я бы посоветовал вам не использовать,
eval()
но если вы это сделаете, убедитесь, что вы подтвердили / занесли в белый список все входные данные.источник
Когда вы используете сторонние данные (например, пользовательский ввод) внутри eval.
В приведенном выше примере это не проблема.
источник
Я явно украду содержимое здесь:
blog.joshuaeichorn.com: использование-eval-in-php
источник
eval()
это всегда зло.источник
eval()
получаю ответ , я сразу же предполагаю, что задал вопрос неправильно; редко это «правильный» ответ, но для общего утверждения, что это всегда зло, просто неверно.Я бы также уделил внимание людям, поддерживающим ваш код.
eval () - это не простой способ просто посмотреть и узнать, что должно произойти, ваш пример не так уж плох, но в других местах это может быть кошмаром.
источник
Лично я считаю, что этот код по-прежнему довольно злой, потому что вы не комментируете то, что он делает. Он также не проверяет свои входные данные на достоверность, что делает его очень хрупким.
Я также считаю, что, поскольку 95% (или больше) случаев использования eval являются активно опасными, небольшая потенциальная экономия времени, которую он может обеспечить в других случаях, не стоит того, чтобы отказываться от плохой практики его использования. Кроме того, позже вам придется объяснять своим миньонам, почему вы используете eval, а они - плохо.
И, конечно же, ваш PHP выглядит как Perl;)
Есть две ключевые проблемы с eval () (как сценарий "инъекционной атаки"):
1) Это может причинить вред 2) Может просто вылететь
и более социальный, чем технический:
3) Это будет соблазнять людей использовать его ненадлежащим образом в качестве ярлыка в другом месте
В первом случае вы рискуете (очевидно, не когда вы оцениваете известную строку) выполнения произвольного кода. Однако ваши входные данные могут быть не такими известными или фиксированными, как вы думаете.
Скорее всего (в этом случае) вы просто упадете, и ваша строка закончится неоправданно непонятным сообщением об ошибке. IMHO, весь код должен выходить из строя настолько аккуратно, насколько это возможно, в противном случае он должен вызывать исключение (как наиболее управляемую форму ошибки).
Я бы предположил, что в этом примере вы кодируете случайно, а не кодируете поведение. Да, оператор перечисления SQL (и вы уверены, что перечисление этого поля? - вы вызывали правильное поле правильной таблицы правильной версии базы данных? Действительно ли он ответил?) Выглядит как синтаксис объявления массива в PHP, но я бы посоветовал вам действительно не найти кратчайшего пути от ввода к выводу, а скорее заняться указанной задачей:
Это примерно то, что делает ваш вариант, но я бы обернул некоторые if и комментарии вокруг него для ясности и безопасности (например, если первое совпадение не совпадает, выбросить исключение или установить нулевой результат).
По-прежнему существуют некоторые возможные проблемы с экранированными запятыми или кавычками, и вам, вероятно, следует распаковать данные, а затем исключить их из кавычек, но он, по крайней мере, обрабатывает данные как данные, а не как код.
С preg_version ваш худший результат, вероятно, будет $ result = null, с версией eval худший неизвестен, но по крайней мере сбой.
источник
eval оценивает строку как код, проблема в том, что если строка каким-либо образом "испорчена", это может привести к огромным угрозам безопасности. Обычно проблема возникает в случае, когда ввод пользователя оценивается в строке, во многих случаях пользователь может ввести код (например, php или ssi), который затем запускается в eval, он будет работать с теми же разрешениями, что и ваш сценарий php, и может использоваться для получения информации / доступа к вашему серверу. Может быть довольно сложно убедиться, что пользовательский ввод правильно очищен, прежде чем передать его eval. Есть и другие проблемы ... некоторые из которых спорны
источник
PHP советует писать код таким образом, чтобы он мог выполняться через call_user_func вместо явных вычислений.
источник
Другая причина
eval
зла заключается в том, что он не может кэшироваться кешами байт-кода PHP, такими как eAccelertor или ACP.источник
Плохое программирование делает eval () злом, а не функцию. Я иногда его использую, так как не могу обойтись без него при динамическом программировании на нескольких сайтах. Я не могу проводить синтаксический анализ PHP на одном сайте, так как я не получу то, что хочу. Я бы просто получил результат! Я счастлив, что существует функция eval (), поскольку она делает мою жизнь намного проще. Пользовательский ввод? Хакеры подключают только плохих программистов. Я не беспокоюсь об этом.
источник
Я предсказываю, что скоро у тебя возникнут серьезные проблемы ...
Честно говоря, в интерпретируемом языке, таком как PHP, совершенно бесполезно использовать такую непомерную функцию, как eval. Я никогда не видел, чтобы eval выполнял программные функции, которые нельзя было бы выполнить другими, более безопасными способами ...
Я полностью согласен с тем, что Eval - это корень всех зол для всех людей, которые думают, что тестирование пользовательского ввода поможет. Подумайте дважды, пользовательский ввод может принимать самые разные формы, и, пока мы говорим, хакеры используют эту функцию, о которой вы не заботились. На мой взгляд, просто избегайте eval вообще.
Я видел созданные примеры злоупотребления функцией eval, превосходящие мои собственные творческие способности. С точки зрения безопасности, избегайте любой ценой, и я бы даже пошел так далеко, что потребовал бы, чтобы это было как минимум опцией в конфигурации PHP, а не «заданным».
источник
eval
. И поэтому для любой функции X: X является корнем всех eval ... э ... зла, так что лучше вообще отказаться от программирования (таким образом вытаскивая ковер из-под этих глупых хакеров, но в конечном итоге все же перехитрив их).Вот решение для запуска кода PHP, извлеченного из базы данных, без использования eval. Разрешает использование всех функций и исключений в области видимости:
$rowId=1; //database row id $code="echo 'hello'; echo '\nThis is a test\n'; echo date(\"Y-m-d\");"; //php code pulled from database $func="func{$rowId}"; file_put_contents('/tmp/tempFunction.php',"<?php\nfunction $func() {\n global \$rowId;\n$code\n}\n".chr(63).">"); include '/tmp/tempFunction.php'; call_user_func($func); unlink ('/tmp/tempFunction.php');
По сути, он создает уникальную функцию с включенным кодом в текстовом файле, включает файл, вызывает функцию, а затем удаляет файл, когда с ней закончено. Я использую это для выполнения ежедневных загрузок / синхронизаций базы данных, где каждый шаг требует уникального кода для обработки. Это решило все проблемы, с которыми я столкнулся.
источник
Раньше я часто использовал eval (), но обнаружил, что в большинстве случаев вам не нужно использовать eval для выполнения трюков. Что ж, у вас есть call_user_func () и call_user_func_array () в PHP. Достаточно статически и динамически вызывать любой метод.
Чтобы выполнить статический вызов, создайте обратный вызов как массив ('class_name', 'method_name') или даже как простую строку, например, 'class_name :: method_name'. Для выполнения динамического вызова используйте обратный вызов в стиле array ($ object, 'method').
Единственное разумное использование eval () - это написать собственный компилятор. Я сделал один, но eval по-прежнему злой, потому что его чертовски сложно отлаживать. Хуже всего то, что фатальная ошибка в исключенном коде приводит к сбою кода, который ее вызвал. Я использовал расширение Parsekit PECL, по крайней мере, чтобы проверить синтаксис, но все равно без радости - попробуйте сослаться на сбой неизвестного класса и всего приложения.
источник
Помимо проблем безопасности, eval () не может быть скомпилирован, оптимизирован или кэширован, поэтому он всегда будет медленнее - намного медленнее - чем обычный PHP-код. Таким образом, использование eval неэффективно, хотя это не делает его злом. (
goto
зло,eval
только плохая практика / вонючий код / уродливый)источник
eval
получает более низкий рейтинг зла, чемgoto
? Это противоположный день?goto
в 5.3.goto
фобианам: есть инструменты, а есть мастера, которые ими пользуются (или нет). Ни разу не инструменты , которые делают профессиональный вид , как на идиота, когда делать ошибки, а неспособность использовать соответствующие инструменты (должным образом). Но всегда виноваты инструменты ...Большинство людей укажут на тот факт, что это может быть опасно, когда вы имеете дело с пользовательским вводом (с которым можно иметь дело).
Для меня хуже всего то, что это снижает ремонтопригодность вашего кода:
источник