当前位置: 首页 > 知识库问答 >
问题:

使用python的eval()与ast.literal_eval()的比较

宰父嘉胜
2023-03-14

我遇到过这样一种情况:一些代码中出现了eval()作为可能的解决方案。现在,我以前从未使用过eval(),但是,我遇到了大量关于它可能导致的潜在危险的信息。也就是说,我对使用它非常谨慎。

我的情况是,我有输入是由用户:

datamap = input('Provide some data here: ')

其中,datamap需要是一个字典。我四处搜索,发现eval()可以解决这个问题。我认为在尝试使用数据之前,我可能能够检查输入的类型,这将是一个可行的安全预防措施。

datamap = eval(input('Provide some data here: ')
if not isinstance(datamap, dict):
    return

我通读了文档,我仍然不清楚这是否安全。在输入数据时或调用datamap变量后,ava是否立即计算数据?

ast模块的.literal\u eval()是唯一安全的选项吗?

共有3个答案

伯鸿达
2023-03-14

eval:这是非常强大的,但如果您接受字符串以从不受信任的输入中求值,则这也是非常危险的。假设正在计算的字符串是“os.system('rm-rf/')”?它将真正开始删除计算机上的所有文件。
ast.literal\u eval:安全地计算表达式节点或包含Python文本或容器显示的字符串。提供的字符串或节点只能由以下Python文本结构组成:字符串、字节、数字、元组、列表、dicts、set、booleans、None、bytes和set。语法:

eval(expression, globals=None, locals=None)
import ast
ast.literal_eval(node_or_string)

例子:

# python 2.x - doesn't accept operators in string format
import ast
ast.literal_eval('[1, 2, 3]')  # output: [1, 2, 3]
ast.literal_eval('1+1') # output: ValueError: malformed string


# python 3.0 -3.6
import ast
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__':{}})

在上面的代码().__class__.__bases__[0]只有对象本身。现在我们实例化了所有的子类,在这里我们的主要在这里输入code目标是从它中找到一个名为n的类。

我们需要从实例化的子类中创建code对象和function对象。这是从CPython访问对象子类并连接系统的另一种方法。

从python 3.7ast.literal_eval()现在更严格。不再允许任意数字的加减法

苍烨然
2023-03-14

ast.literal\u eval()只认为Python语法的一小部分是有效的:

提供的字符串或节点只能由以下Python文本结构组成:字符串、字节、数字、元组、列表、dicts、set、boolean和None

\u import\u('os').system('rm-rf/a-path-you-really-care-about')传递到ast.literal\u eval()将引发错误,但eval()将愉快地删除您的文件。

因为看起来您只允许用户输入普通字典,所以请使用ast.literal\u eval()。它能安全地做你想做的事,仅此而已。

贺飞
2023-03-14

datamap=eval(input('Provide some data here:'))意味着您在认为代码是否不安全之前实际评估了它。它会在调用函数后立即计算代码。另请参见eval的危险。

ast.literal\u eval如果输入不是有效的Python数据类型,则会引发异常,因此如果不是,则不会执行代码。

在需要时使用ast.literal\u eval。您通常不应该对文本Python语句求值。

 类似资料:
  • 问题内容: 我遇到了一些代码,将其作为可能的解决方案。现在,我从来没有使用过,但是,我遇到了很多有关它可能引起的潜在危险的信息。也就是说,我对使用它非常谨慎。 我的情况是我有一个用户输入: 哪里需要一本字典。我四处搜寻,发现可以解决这个问题。我认为我可以在尝试使用数据之前检查输入的类型,这将是可行的安全预防措施。 我通读了文档,但仍不清楚这是否安全。是否在输入数据后或调用变量后立即评估数据? 该a

  • 问题内容: 我将2 MB的数据作为字符串转换为字典。输入已以JSON序列化。 无论如何,我当前正在使用ast.literal_eval,并且得到了我想要的字典,但是当我尝试仅运行eval时,它似乎运行得更快,并且还返回了相同的结果。 当eval正常工作时,是否有任何理由使用ast模块或json模块? 问题答案: 我真的不喜欢这种对stackoverflow(以及其他地方)的态度,告诉没有任何上下文

  • 本文向大家介绍Python中函数eval和ast.literal_eval的区别详解,包括了Python中函数eval和ast.literal_eval的区别详解的使用技巧和注意事项,需要的朋友参考一下 前言 众所周知在Python中,如果要将字符串型的list,tuple,dict转变成原有的类型呢? 这个时候你自然会想到eval. eval函数在python中做数据类型的转换还是很有用的。它的

  • 问题内容: 我有一个字符串,我想将其转换为它代表的对象。使用给 因为它不允许构造对象(即调用)。无论如何,要么可以正确地处理此问题,要么可以确保防止代码注入? 问题答案: 跟随伊格纳西奥·巴斯克斯(Ignacio Vazquez-brams)的想法: 产量

  • 本文向大家介绍Python中的exec、eval使用实例,包括了Python中的exec、eval使用实例的使用技巧和注意事项,需要的朋友参考一下 通过exec可以执行动态Python代码,类似Javascript的eval功能;而Python中的eval函数可以计算Python表达式,并返回结果(exec不返回结果,print(eval("…"))打印None); 这里有个scope(命名空间,