关于Python中的"eval is evil"和"同意成年人"

zha*_*hen 9 python duck-typing conventions

我看到许多人说"eval是邪恶的/危险的/不安全的",因为人们可以这样做:

eval("os.system('rm -rf /')")
Run Code Online (Sandbox Code Playgroud)

而在其他帖子中,pythoner被认为是" 同意成人 ",你不必进行类型检查,因为python是鸭子打字的样式.

那么下面的代码呢:

def foo(duck):
    duck.quack()

class EvilDuck(object):
    def quack(self):
        os.system('rm -rf /')

foo(EvilDuck())
Run Code Online (Sandbox Code Playgroud)

你通常如何避免这种情况?pythoner何时同意成年人,何时不同意?

Ry-*_*Ry- 18

eval是邪恶的,因为用户输入在某些时候进入它.你没有(好吧,不应该)担心代码假装不删除所有文件,因为代码可以做到这一点 - tada:

def foo(duck):
    duck.quack()

class EvilDuck(object):
    os.system('rm -rf /')

    def quack(self):
        pass
Run Code Online (Sandbox Code Playgroud)

并且rm -rf /很有可能不工作.;)

基本上,"同意成年人"是"信任你的代码".eval是"信任所有代码".根据您获得该代码的位置,eval可以没问题,但99%的时间都没有必要,而且也很难保证安全.

  • 完全没有理由使用eval进行数据序列化和解包.你可能很容易我们泡菜和/或json.它还会使您的代码变得更加可怕,因为引用数据结构以便您可以进行eval on来恢复它很难. (6认同)
  • 我认为如果你不知道你正在评估的字符串的来源,eval()是邪恶的.如果源是已知的(当然可靠),我没有看到问题.我使用eval()来解释由另一个受信任的应用程序通过安全网络发送的数据结构.这有点像'goto`讨论.没有人喜欢goto,但它可以大大简化深度嵌套if.每个规则都有例外,一如既往. (3认同)

hol*_*web 5

对于Python来说,试图阻止他们从程序中执行命令,他们可以轻松地直接输入shell命令行而不涉及Python,这似乎很愚蠢.

鸭子打字是可以的,因为它不涉及运行由J. Random internet-User编写的代码.您(可能)是以与其预期用途一致的方式调用您定义的对象的capabale.

eval()exec(也是Python 3中的一个函数,但Python 2中的一个语句)在应用于经过充分验证的用户输入时被认为是危险的,因为如果没有验证,您就会对自己的恶意用户群的意愿敞开大门.

换句话说,代码就像

eval(raw_input("How may I hack you today? "))
Run Code Online (Sandbox Code Playgroud)

是危险的,因为用户可能选择进入

os.system("switch off your antivirus protection")
Run Code Online (Sandbox Code Playgroud)

或类似涉及风险的其他事情.