Я ищу "безопасную" функцию eval, чтобы реализовать вычисления, подобные электронным таблицам (с использованием numpy / scipy).
Функциональные возможности для этого (модуль rexec) были удалены из Python, начиная с 2.3, из-за явно не исправляемых проблем безопасности. Есть несколько сторонних хаков, которые призваны сделать это - самое продуманное решение, которое я нашел, это этот рецепт Python Cookbok, "safe_eval".
Достаточно ли я в безопасности, если использую это (или что-то подобное) для защиты от вредоносного кода, или я застрял в написании собственного парсера? Кто-нибудь знает какие-нибудь лучшие альтернативы?
Обновлено: Я только что обнаружил RestrictedPython, который является частью Zope. Любые мнения по этому поводу приветствуются.






Написание собственного парсера может быть забавным! Это может быть лучший вариант, потому что люди ожидают использовать знакомый синтаксис электронных таблиц (Excel и т. д.), А не Python при вводе формул. Я не знаком с safe_eval, но полагаю, что что-то подобное определенно может быть использовано.
Хотя этот код выглядит вполне безопасным, я всегда считал, что любой достаточно мотивированный человек может взломать его при наличии достаточного времени. Я действительно думаю, что потребуется немало решимости, чтобы пройти через это, но я почти уверен, что это можно сделать.
Даниэль, Джиндзя реализует среду песочницы, которая может быть вам полезна, а может и не оказаться. Насколько я помню, он еще не «понимает» понимания списков.
Полагаю, это зависит от вашего определения сейфа. Безопасность во многом зависит от того, что вы передаете и что вам разрешено передавать в контексте. Например, если файл передан, я могу открывать произвольные файлы:
>>> names['f'] = open('foo', 'w+')
>>> safe_eval.safe_eval("baz = type(f)('baz', 'w+')", names)
>>> names['baz']
<open file 'baz', mode 'w+' at 0x413da0>
Кроме того, среда очень ограничена (вы не можете передавать модули), поэтому вы не можете просто передать модуль служебных функций, таких как re или random.
С другой стороны, вам не нужно писать собственный парсер, вы можете просто написать свой собственный оценщик для python ast:
>>> import compiler
>>> ast = compiler.parse("print 'Hello world!'")
Таким образом, надеюсь, вы сможете реализовать безопасный импорт. Другая идея - использовать Jython или IronPython и воспользоваться возможностями песочницы Java / .Net.
Если вам просто нужно записать и прочитать некоторую структуру данных в Python, и вам не нужна фактическая способность выполнять собственный код, этот вариант лучше подходит: http://code.activestate.com/recipes/364469-safe-eval/
Это гарантирует, что код не выполняется, оцениваются только статические структуры данных: строки, списки, кортежи, словари.
Необходимая вам функциональность находится в службах языка компилятора, см. http://docs.python.org/library/language.html Если вы определяете свое приложение для приема только выражений, вы можете скомпилировать ввод как выражение и получить исключение, если это не так, например если есть точки с запятой или формы утверждения.
Вы можете использовать scipy / numpy в электронной таблице с помощью Resolver One. resolversystems.com