Использование Python eval () против ast.буквальное функцию eval()?
у меня есть ситуация с некоторым кодом, где 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: строк, чисел, кортежей, списков, диктов, логических значений и None.
передает __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')
оценка:
Это очень мощно, но также очень опасно, если вы принимаете строки для оценки из ненадежного ввода. Предположим, что оцениваемая строка - " 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.