Использование 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() единственный безопасный вариант?

577   6  

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

    Ничего не найдено.