diff --git a/PIL/ImageMath.py b/PIL/ImageMath.py
index 6548b03..5312207 100644
--- a/PIL/ImageMath.py
+++ b/PIL/ImageMath.py
@@ -219,7 +219,18 @@ def eval(expression, _dict={}, **kw):
if hasattr(v, "im"):
args[k] = _Operand(v)
- out = builtins.eval(expression, args)
+ compiled_code = compile(expression, "<string>", "eval")
+ def scan(code):
+ for const in code.co_consts:
+ if type(const) == type(compiled_code):
+ scan(const)
+
+ for name in code.co_names:
+ if name not in args and name != "abs":
+ raise ValueError("'{0}' not allowed".format(name))
+
+ scan(compiled_code)
+ out = builtins.eval(expression, {"__builtins": {"abs": abs}}, args)
try:
return out.im
except AttributeError:
diff --git a/Tests/test_imagemath.py b/Tests/test_imagemath.py
index eaeb711..da9d1d7 100644
--- a/Tests/test_imagemath.py
+++ b/Tests/test_imagemath.py
@@ -45,6 +45,12 @@ def test_ops():
assert_equal(pixel(ImageMath.eval("float(B)**2", images)), "F 4.0")
assert_equal(pixel(ImageMath.eval("float(B)**33", images)), "F 8589934592.0")
+def test_logical():
+ assert_exception(ValueError, ImageMath.eval("exit()"))
+ assert_exception(ValueError, ImageMath.eval("(lambda:(exit()))()"))
+ assert_exception(ValueError, ImageMath.eval("(lambda:(exit())())()"))
+
+
def test_logical():
assert_equal(pixel(ImageMath.eval("not A", images)), 0)
assert_equal(pixel(ImageMath.eval("A and B", images)), "L 2")