Skip to content

Commit c930be0

Browse files
committed
Restrict builtins within lambdas for ImageMath.eval
1 parent 75b69dd commit c930be0

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

Tests/test_imagemath.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,17 @@ def test_ops():
5252
assert pixel(ImageMath.eval("float(B)**33", images)) == "F 8589934592.0"
5353

5454

55-
def test_prevent_exec():
55+
@pytest.mark.parametrize(
56+
"expression",
57+
(
58+
"exec('pass')",
59+
"(lambda: exec('pass'))()",
60+
"(lambda: (lambda: exec('pass'))())()",
61+
),
62+
)
63+
def test_prevent_exec(expression):
5664
with pytest.raises(ValueError):
57-
ImageMath.eval("exec('pass')")
65+
ImageMath.eval(expression)
5866

5967

6068
def test_logical():

src/PIL/ImageMath.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,18 @@ def eval(expression, _dict={}, **kw):
246246
if hasattr(v, "im"):
247247
args[k] = _Operand(v)
248248

249-
code = compile(expression, "<string>", "eval")
250-
for name in code.co_names:
251-
if name not in args and name != "abs":
252-
raise ValueError(f"'{name}' not allowed")
249+
compiled_code = compile(expression, "<string>", "eval")
253250

251+
def scan(code):
252+
for const in code.co_consts:
253+
if type(const) == type(compiled_code):
254+
scan(const)
255+
256+
for name in code.co_names:
257+
if name not in args and name != "abs":
258+
raise ValueError(f"'{name}' not allowed")
259+
260+
scan(compiled_code)
254261
out = builtins.eval(expression, {"__builtins": {"abs": abs}}, args)
255262
try:
256263
return out.im

0 commit comments

Comments
 (0)