Использование python's eval () против ast.буквальная оценка ()?
у меня есть ситуация с некоторым кодом, где 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() единственный безопасный вариант?
6 ответов:
datamap = eval(raw_input('Provide some data here: '))означает, что вы на самом деле оценить код до вы считаете, что это небезопасно или нет. Он вычисляет код, как только функция вызывается. Смотрите также опасностиeval.
ast.literal_evalвызывает исключение, если входные данные не являются допустимым типом данных Python, поэтому код не будет выполнен, если это не так.использовать
ast.literal_evalвсякий раз, когда вам нужноeval. Вы не должны, как правило, оценивают буквального выражения Python.
ast.literal_eval()считается допустимым только небольшое подмножество синтаксиса Python:предоставленная строка или узел могут состоять только из следующих литеральных структур Python: строки, числа, кортежи, списки, дикты, логические значения и нет.
передает
__import__('os').system('rm -rf /a-path-you-really-care-about')наast.literal_eval()выдает ошибку, ноeval()С удовольствием протрите ваш диск.поскольку похоже, что вы только позволяете пользователю вводить простой словарь, используйте
ast.literal_eval(). Это безопасно делает то, что вы хотите, и ничего больше.
в Python готовностью в своей оценке, так
eval(raw_input(...))будет оценивать ввод пользователя, как только он попадает вeval, независимо от того, что вы делаете потом с данными. Таким образом, это небезопасно, особенно, когда выevalпользовательский ввод.использовать
ast.literal_eval.
например, ввод этого в командной строке будет очень, очень плохо для вас:
__import__('os').system('rm -rf /a-path-you-really-care-about')
eval: Это очень мощно, но также очень опасно, если вы принимаете строки для оценки из ненадежного ввода. Предположим, что вычисляемая строка - " os.система ('rm-rf /')"? Он действительно начнет удалять все файлы на вашем компьютере.
АСТ.literal_eval: Безопасно вычислить узел выражения или строку, содержащую литерал Python или контейнер отображения. Предоставленная строка или узел могут состоять только из следующих литеральных структур Python: строки, байты, числа, кортежи, списки, дикты, наборы, логические значения, нет, байты и наборы.
синтаксис:eval(expression, globals=None, locals=None) ast.literal_eval(node_or_string)пример:
ast.literal_eval("1+1") # output : 2 ast.literal_eval("{'a': 2, 'b': 3, 3:'xyz'}") # output : {'a': 2, 'b': 3, 3:'xyz'} # type dictionary ast.literal_eval("",{}) # output : Syntax Error required only one parameter ast.literal_eval("__import__('os').system('rm -rf /')") # output : error eval("__import__('os').system('rm -rf /')") # output : start deleting all the files on your computer. # restricting using global and local variables eval("__import__('os').system('rm -rf /')",{'__builtins__':{}},{}) # output : Error due to blocked imports by passing '__builtins__':{} in global # But still eval is not safe. we can access and break the code as given below s = """ (lambda fc=( lambda n: [ c for c in ().__class__.__bases__[0].__subclasses__() if c.__name__ == n ][0] ): fc("function")( fc("code")( 0,0,0,0,"KABOOM",(),(),(),"","",0,"" ),{} )() )() """ eval(s, {'__builtins__':{}})
Если все, что вам нужно, это пользовательский словарь, возможно лучшее решение
json.loads. Основное ограничение заключается в том, что JSON dicts требует строковых ключей. Также вы можете предоставить только литеральные данные, но это также относится кliteral_eval.
Я застрял с
ast.literal_eval(). Я пробовал его в IntelliJ IDEA debugger, и он продолжал возвращатьсяNoneна вывод отладчика.но позже, когда я назначил его выход переменной и напечатал его в коде. Это сработало отлично. Пример совместного использования кода:
import ast sample_string = '[{"id":"XYZ_GTTC_TYR", "name":"Suction"}]' output_value = ast.literal_eval(sample_string) print(output_value)его версия python 3.6.
Comments