Python: Using sympy.sympify to perform a safe eval() on mathematical functions
eval, parsing, python, sympy
Solution
Use sympy, it's a way safer option.
import sympy
from sympy.core.function import Function
from sympy.core import S
from sympy import sympify
from sympy.functions import im
from scipy.special import wofz
class Wofz(Function):
is_real = True
@classmethod
def _should_evalf(csl,arg):
return True
def as_base_exp(cls):
return cls,S.One
def _eval_evalf(cls, prec):
return sympy.numbers.Number(im(wofz(float(cls.args[0]))))
print sympify("Wofz(2)",{'Wofz':Wofz}).evalf()
Output (you'll have to handle the imaginary part somehow):
0.340026217066065
Problem
I am writing a program where users need to be able to use self written mathematical functions containing functions from numpy and scipy, eg. scipy.special.wofz(). These functions will be stored in files and imported as strings by the program. I looked around and saw, that eval() or exec() are not a safe way to do it. eg. here. The security issue would be that good users load a file from evil users who get access to the good users system. I was thinking about doing something like this: ``` #!/bin/python from scipy.special import * from numpy import * import sympy # Define variable a vars = {"a":1} # This is the string I get from a file string = "wofz(a)" parsed_string = sympy.sympify(string) parsed_string.evalf(subs=vars) ``` However, this does not work. It only returns: ``` wofz(a) ``` wofz(a) is not evaluated. Is this even supposed to work that way? I had another idea: So I thought, once this mathematical function got through sympify, it should be safe. I could just simply do something like this: ``` globals = {wofz:wofz} eval(str(parsed_string), vars, globals) ``` which works fine and returns: ``` (0.36787944117144233+0.60715770584139372j) ``` Is that safe? I know it's not nice. Please help.