【问题标题】:Python Eval make datetime module availablePython Eval 使 datetime 模块可用
【发布时间】:2020-05-21 12:47:48
【问题描述】:

我正在寻找一种方法来使 datetime 的函数在 eval 表达式中可用。这将是最小的工作代码

import datetime
input_string = 'from_{today:%m-%d}_to_{yesterday:%m-%d}'
input_dict = {
        'today': eval('datetime.datetime.today()', {'datetime': datetime}, {}),
        'yesterday': eval('datetime.datetime.today()-datetime.timedelta(days=1)', {'datetime': datetime}, {})
        }
print(input_string.format(**input_dict))

但这并不妨碍 eval 函数执行__builtins__ 的方法。如何阻止它访问__builtins__

【问题讨论】:

  • 你的意思是把#放在eval_dict = {format_key: eval(之前还是错字?
  • 即使你完成了这项工作,一个有经验的用户几乎肯定能够突破你的沙箱并造成麻烦。如果这是真实的(不是玩具项目),那么您可能应该编写一个适当的解析器而不是使用 eval
  • 我认为您只需要一个 function 接受输入字符串,然后根据需要计算 todayyesterday 的值以传递给输入字符串的 @987654328 @ 方法。不需要eval
  • 没错。然而,今天和昨天只是示例日期时间。用户可以灵活地访问整个日期时间模块,包括通过 timedelta 进行计算。
  • 是的,这是个坏主意。 eval 是全有或全无;它评估一个有效的 Python 表达式,无论该表达式包含什么。您不能将其限制为您期望用户输入的表达式。

标签: python datetime eval


【解决方案1】:

假设你想做我认为你想做的事:

import datetime
import math

user_input = input()

# set locals to a dict containing only datetime
# set globals to an empty dict  
eval(user_input, {'datetime': datetime}, dict())

如果用户输入“datetime.date.today()”,那么您会得到“datetime.date(2020, 2, 5)”。如果用户输入“math.acos(0.5)”,则会得到“NameError: name 'math' is not defined”。

注意:正如其他人所说,出于安全原因,我并不真正支持这种方法。例如。用户可以输入'"datetime.date.today()" + quit()' 来退出您的程序,或者更糟。

【讨论】:

    【解决方案2】:

    对于 eval 的第三个参数,使用它而不是 {}:

         {'__builtins__': None}
    

    以这种方式明确限制所有内置函数,您需要的除外。使用第二个参数仅列出您希望授予 eval() 访问权限的特定对象。

    许多害怕 eval() 的人说不要在用户输入上使用它,通过正确使用第二个和第三个参数以及对输入的明智过滤来消除它可以用于完全防火墙式锁定的想法字符串(即不包括“__”)和异常处理。

    • 关于它是全有或全无的评论是完全错误的。但是您的代码尝试使用鲜为人知的第二个和第三个参数,所以您知道...

    • 安全风险的 quit() 示例是错误信息。它适用于仅带有第一个参数表达式 的 eval 的使用,它隐含地告诉解释器没有限制和所有访问。但这不是你的问题或你的代码。

    为了允许这样的危险,在通过第二个和第三个参数正确关闭所有访问之后,您必须显式启用它们,如下所示:

         {'__builtins__': {'quit': quit}})
    

    ...或者更糟...

         {'__builtins__': {'eval': eval}})
    

    所以不要那样做。

    【讨论】:

    • 内容丰富的文章和讨论。作者在讨论中确实做出了让步,尽管可怕的标题仍然存在。总而言之,如果上下文允许,可以降低风险。我专门回答了 OP 的问题:“如何防止它访问 builtins?”准确和正确。 OP 并未暗示这是不受信任的字符串。因此,这里的离题和无缘无故的永不言败者提供的示例仍然是错误的,或者至少是不明智的。我当然建议任何人阅读您发布的文章并在适当的情况下应用其中的知识。
    猜你喜欢
    • 2014-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-06
    • 2015-06-09
    相关资源
    最近更新 更多