允许 eval() 仅评估算术表达式和特定函数。

huangapple go评论68阅读模式
英文:

Allow eval() to evaluate only arithmetic expressions and certain functions

问题

我有一个计算器它使用`eval()`函数来评估表达式但我意识到使用`eval()`是危险的因为它可以用来在计算机上运行任意代码

因此我希望它只能评估算术表达式和某些定义好的函数从另一个文件中导入)。

consolecalc.py
```py
from mymathmodule import *
import time
while True:
    try:   
       Choose = '''选择你的功能:
       1百分比计算器
       2阶乘计算器
       3基本算术+-*/
       '''
       for character in Choose:
        print(character, end="", flush=True)
        time.sleep(0.006)
       a = int(input(':'))
       if a == 1:
           percentagecalc()
       elif a == 2:
           factorialcalc()
       elif a == 3:
           calc = input("输入表达式")
           print("表达式结果为",eval(calc))
       else:
           print("\n糟糕出错了请重试...") 
       time.sleep(0.6)
    except:
       print("\n糟糕出错了请重试...")    
       time.sleep(0.6)

定义的函数在mymathmodule.py中,我只希望eval()能够评估这些函数以及基本算术表达式。

我还想知道是否有任何替代eval()的方法可以为我做到这一点...

英文:

I have a calculator that uses the eval() function to evaluate expressions, but I am aware of the fact that using eval() is dangerous as it can be used to run arbitrary code on the machine.

So, I want it to only be able to evaluate arithmetic expressions and certain defined functions (imported from another file).

consolecalc.py:

from mymathmodule import *
import time
while True:
    try:   
       Choose = '''Choose your function:
       1: Percentage calculator
       2: Factorial calculator
       3: Basic arithmetics (+-*/)
       '''
       for character in Choose:
        print(character, end="", flush=True)
        time.sleep(0.006)
       a = int(input(':'))
       if a == 1:
           percentagecalc()
       elif a == 2:
           factorialcalc()
       elif a == 3:
           calc = input("Enter Expression:")
           print("Expression equals:",eval(calc))
       else:
           print("\nOops! Error.  Try again...") 
       time.sleep(0.6)
    except:
       print("\nOops! Error.  Try again...")    
       time.sleep(0.6)

The defined functions are present in mymathmodule.py and I only want eval() to be able to evaluate those along with basic arithmetic expressions

I would also like to know if there are any alternatives to eval() that could do this for me...

答案1

得分: 2

你可以将全局和本地命名空间作为字典传递给eval()。如果全局命名空间包含__builtins__,则无法从传递的字符串中调用任何正常的内置函数。您还可以使用这种方式提供您自己的函数,例如:

globs = {
    "__builtins__": {},
    "sqrt": my_sqrt_fun
}

如果将其传递给eval,那么输入中的sqrt将调用my_sqrt_fun

eval("3 + sqrt(3)", globs, {})

当使用河马操作符在表达式内发生赋值时,它将设置在本地字典中,因此使用空字典。您可以使用这种方式允许设置变量,但为了防止用户覆盖任何内容,只使用该字典来实现此目的。

例如,传递exec将引发NameError,因此不能以这种方式执行任意代码。

英文:

You can pass the global and local namespace to eval() as a dict. If the globals contain __builtins__ none of the normal builtin functions can be called from the passed string. You can also use this to provide your own functions, e.g.

globs = {
    "__builtins__": {},
    "sqrt": my_sqrt_fun
}

If you pass that to eval then sqrt in the input will call my_sqrt_fun

eval("3 + sqrt(3)", globs, {})

When an assignment occurs within the expression using the walrus operator, it will be set in the local dictionary, hence the empty dictionary. You could use this allow variables to be set, but to prevent users from overwriting anything, use that dictionary only for that purpose.

Passing e.g. exec will raise a NameError, so no arbitrary code can be executed this way.

huangapple
  • 本文由 发表于 2023年2月24日 14:21:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75553199.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定