У меня есть ситуация с каким-то кодом, где я eval()
нашел возможное решение. Теперь мне никогда не приходилось использовать eval()
раньше, но я наткнулся на множество информации о потенциальной опасности, которую это может вызвать. Тем не менее, я очень осторожен с его использованием.
Моя ситуация такова, что у меня есть ввод данных от пользователя:
datamap = raw_input('Provide some data here: ')
Где datamap
должен быть словарь. Я искал вокруг и обнаружил, что eval()
может решить это. Я подумал, что смогу проверить тип ввода, прежде чем пытаться использовать данные, и это будет реальной мерой безопасности.
datamap = eval(raw_input('Provide some data here: ')
if not isinstance(datamap, dict):
return
Я прочитал документы, и мне все еще неясно, будет ли это безопасно или нет. Оценивает ли eval данные сразу после их ввода или после datamap
вызова переменной?
Является ли ast
модуль .literal_eval()
единственным безопасным вариантом?
ast.literal_eval("1 & 1")
выдаст ошибку ноeval("1 & 1")
не будет.ast.literal_eval
что-то подобное (например, вы можете реализовать парсер вручную).ast.literal_eval()
допустимо только небольшое подмножество синтаксиса Python:Переход
__import__('os').system('rm -rf /a-path-you-really-care-about')
вast.literal_eval()
вызывает ошибку, но сeval()
удовольствием стереть ваш диск.Поскольку, похоже, вы позволяете пользователю вводить простой словарь, используйте
ast.literal_eval()
. Он безопасно делает то, что вы хотите, и ничего больше.источник
eval: это очень мощно, но также очень опасно, если вы принимаете строки для оценки из ненадежного ввода. Предположим, что оцениваемой строкой является "os.system ('rm -rf /')"? Это действительно начнет удалять все файлы на вашем компьютере.
ast.literal_eval: Безопасный анализ узла выражения или строки, содержащей литерал Python или отображение контейнера. Предоставленная строка или узел может состоять только из следующих литеральных структур Python: строк, байтов, чисел, кортежей, списков, диктов, наборов, логических значений, None, байтов и наборов.
Синтаксис:
Пример:
В приведенном выше коде
().__class__.__bases__[0]
ничего, кроме самого объекта. Теперь мы создали все подклассы , и наша главнаяenter code here
цель - найти в нем один класс с именем n .Нам нужно
code
возражать иfunction
возражать от созданных экземпляров подклассов. Это альтернативный способCPython
доступа к подклассам объекта и присоединения системы.В python 3.7 ast.literal_eval () теперь стал более строгим. Сложение и вычитание произвольных чисел больше не допускаются. ссылка на сайт
источник
ast.literal_eval("1+1")
не работает в Python 3.7 и, как уже было сказано, literal_eval должен быть ограничен литералами этих нескольких структур данных. Он не должен быть в состоянии анализировать двоичную операцию.KABOOM
код, пожалуйста? Нашел здесь:KABOOM
KABOOM
хорошо объясняется здесь: nedbatchelder.com/blog/201206/eval_really_is_dangerous.htmlPython стремится к своей оценке, поэтому
eval(raw_input(...))
он оценит ввод пользователя, как только он попадетeval
, независимо от того, что вы будете делать с данными впоследствии. Поэтому это небезопасно , особенно когда вы вводитеeval
пользователя.Использование
ast.literal_eval
.Например, ввод этого в приглашении будет очень и очень плохим для вас:
источник
Если все, что вам нужно, это пользовательский словарь, возможно лучшее решение
json.loads
. Основным ограничением является то, что для json требуется строковые ключи. Также вы можете предоставить только буквальные данные, но это также относится и кliteral_eval
.источник
Я застрял с
ast.literal_eval()
. Я пробовал это в отладчике IntelliJ IDEA, и он продолжал возвращатьсяNone
на выходе отладчика.Но позже, когда я назначил ее вывод переменной и напечатал ее в коде. Работало нормально. Пример совместного использования кода:
Его версия Python 3.6.
источник