Python: make eval safe

flybywire picture flybywire · Aug 18, 2010 · Viewed 31.7k times · Source

I want an easy way to do a "calculator API" in Python.

Right now I don't care much about the exact set of features the calculator is going to support.

I want it to receive a string, say "1+1" and return a string with the result, in our case "2".

Is there a way to make eval safe for such a thing?

For a start I would do

env = {}
env["locals"]   = None
env["globals"]  = None
env["__name__"] = None
env["__file__"] = None
env["__builtins__"] = None

eval(users_str, env)

so that the caller cannot mess with my local variables (or see them).

But I am sure I am overseeing a lot here.

Are eval's security issues fixable or are there just too many tiny details to get it working right?

Answer

Alex Martelli picture Alex Martelli · Aug 18, 2010

are eval's security issues fixable or are there just too many tiny details to get it working right?

Definitely the latter -- a clever hacker will always manage to find a way around your precautions.

If you're satisfied with plain expressions using elementary-type literals only, use ast.literal_eval -- that's what it's for! For anything fancier, I recommend a parsing package, such as ply if you're familiar and comfortable with the classic lexx/yacc approach, or pyparsing for a possibly more Pythonic approach.