Depending on how complicated your expressions are, ast.literal_eval may be a safer alternative.
Depending on how complicated your expressions are, ast.literal_eval may be a safer alternative.
If you're the only person using that app and thus don't need to be worried about security issues, just keep using eval() or exec().
Otherwise, just use a safe library for the specific task you need. E.g. numexpr I guess for a calculator.
I have a usecase within a webapplication, where I want to let users input some text, which will be evaluated as a math expression.
The most straightforward method is to tell the users to use python syntax and then throw it into eval, and all is good.
The problem is that there are a bunch of crazy ways to exploit eval to attain "arbitrary code execution". Many discussions arond the web talk of ways to make eval safe(r), but all of them come with more exploits. Best attempt I've seen is Asteval, which lets me use python syntax for the math, however, the author cannot provide any evidence that it is safe to use.
Next possibility is to write a parser for the desired language constructs, which is certainly possible for simple arithmetic, but what if I wanted programming constructs like loops and lists an stuff? Then it gets a bit involved.
So, does anyone know of a safe way to execute untrusted Python code in a safe manner?
-- Edit: I've rephrased my post to be a bit more clear
Alternative to 'eval'
library - Alternative math evaluators in Python - Software Recommendations Stack Exchange
Alternative to Python's eval in Lua
Alternatives to using eval()
Videos
» pip install evalidate
import operator
ops = { 'or': operator.or_, 'and': operator.and_ }
print opsop
It's not clear to me how @CatPlusPlus's solution will evaluate any boolean expression. Here is an example from the pyparsing wiki examples page of a Boolean expression parser/evaluator. Here are the test cases for this script:
p = True
q = False
r = True
test = ["p and not q",
"not not p",
"not(p and q)",
"q or not p and r",
"q or not (p and r)",
"p or q or r",
"p or q or r and False",
]
for t in test:
res = boolExpr.parseString(t)[0]
print t,'\n', res, '=', bool(res),'\n'
datamap = eval(input('Provide some data here: ')) means that you actually evaluate the code before you deem it to be unsafe or not. It evaluates the code as soon as the function is called. See also the dangers of eval.
ast.literal_eval raises an exception if the input isn't a valid Python datatype, so the code won't be executed if it's not.
Use ast.literal_eval whenever you need eval. You shouldn't usually evaluate literal Python statements.
ast.literal_eval() only considers a small subset of Python's syntax to be valid:
The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and
None.
Passing __import__('os').system('rm -rf /a-path-you-really-care-about') into ast.literal_eval() will raise an error, but eval() will happily delete your files.
Since it looks like you're only letting the user input a plain dictionary, use ast.literal_eval(). It safely does what you want and nothing more.