Вопрос-Ответ

Why should exec() and eval() be avoided?

Почему следует избегать exec() и eval()?

Я видел это несколько раз в разных местах, но так и не нашел удовлетворительного объяснения, почему это должно быть так.

Итак, надеюсь, один из них будет представлен здесь. Почему мы не должны (по крайней мере, в целом) использовать exec() и eval()?

РЕДАКТИРОВАТЬ: Я вижу, что люди предполагают, что этот вопрос относится к веб–серверам - это не так. Я понимаю, почему передача неаналитизированной строки exec может быть плохой. Это плохо в приложениях, отличных от web?

Переведено автоматически
Ответ 1

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

Пример: Я написал код, который считывает строковые ключи и значения и устанавливает соответствующие поля в объекте. Это выглядело так:

for key, val in values:
fieldName = valueToFieldName[key]
fieldType = fieldNameToType[fieldName]
if fieldType is int:
s = 'object.%s = int(%s)' % (fieldName, fieldType)
#Many clauses like this...

exec(s)

Этот код не так уж страшен для простых случаев, но по мере появления новых типов он становился все более и более сложным. Когда были ошибки, они всегда срабатывали при вызове exec, поэтому трассировка стека не помогла мне их найти. В конце концов я переключился на немного более длинную и менее продуманную версию, в которой каждое поле задается явно.

Первое правило ясности кода заключается в том, что каждую строку вашего кода должно быть легко понять, глядя только на строки рядом с ней. Вот почему не рекомендуется использовать goto и глобальные переменные. exec и eval позволяют легко нарушить это правило.

Ответ 2

Когда вам нужны exec и eval, да, они вам действительно нужны.

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

Вы можете, при правильном экранировании и фильтрации, безопасно использовать exec и eval. Но программист, который сразу обращается к exec / eval для решения проблемы (потому что он не понимает других возможностей, которые предоставляет язык), не тот программист, который сможет выполнить эту обработку правильно; это будет тот, кто не разбирается в обработке строк и просто слепо объединяет подстроки, что приводит к хрупкому небезопасному коду.

Это приманка строк. Разбрасывание сегментов строк выглядит просто и обманывает наивных программистов, заставляя их думать, что они понимают, что делают. Но опыт показывает, что результаты почти всегда неверны в каком-то угловом (или не очень угловом) случае, часто с потенциальными последствиями для безопасности. Вот почему мы говорим, что eval - это зло. Вот почему мы говорим, что регулярное выражение для HTML - это зло. Вот почему мы настаиваем на параметризации SQL. Да, вы можете исправить все эти вещи с помощью ручной обработки строк... но если вы еще не поняли, почему мы так говорим, скорее всего, вы не поймете.

Ответ 3

Security aside, eval and exec are often marked as undesirable because of the complexity they induce. When you see a eval call you often don't know what's really going on behind it, because it acts on data that's usually in a variable. This makes code harder to read.

Invoking the full power of the interpreter is a heavy weapon that should be only reserved for very tricky cases. In most cases, however, it's best avoided and simpler tools should be employed.

That said, like all generalizations, be wary of this one. In some cases, exec and eval can be valuable. But you must have a very good reason to use them. See this post for one acceptable use.

Ответ 4

eval() and exec() can promote lazy programming. More importantly it indicates the code being executed may not have been written at design time therefore not tested. In other words, how do you test dynamically generated code? Especially across browsers.

2023-06-20 10:07 python