Skip to content

Commit d7f60d1

Browse files
authored
Merge pull request #5923 from radarhere/imagemath_eval
Restrict builtins for ImageMath.eval()
2 parents 1efb1d9 + 8531b01 commit d7f60d1

File tree

3 files changed

+21
-1
lines changed

3 files changed

+21
-1
lines changed

Tests/test_imagemath.py

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import pytest
2+
13
from PIL import Image, ImageMath
24

35

@@ -50,6 +52,11 @@ def test_ops():
5052
assert pixel(ImageMath.eval("float(B)**33", images)) == "F 8589934592.0"
5153

5254

55+
def test_prevent_exec():
56+
with pytest.raises(ValueError):
57+
ImageMath.eval("exec('pass')")
58+
59+
5360
def test_logical():
5461
assert pixel(ImageMath.eval("not A", images)) == 0
5562
assert pixel(ImageMath.eval("A and B", images)) == "L 2"

docs/releasenotes/9.0.0.rst

+8
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,14 @@ To prevent attempts to slow down loading times for images, if an image has conse
116116
duplicate tiles that only differ by their offset, only load the last tile. Credit to
117117
Google's `OSS-Fuzz`_ project for finding this issue.
118118

119+
Restrict builtins available to ImageMath.eval
120+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
121+
122+
To limit :py:class:`PIL.ImageMath` to working with images, Pillow will now restrict the
123+
builtins available to :py:meth:`PIL.ImageMath.eval`. This will help prevent problems
124+
arising if users evaluate arbitrary expressions, such as
125+
``ImageMath.eval("exec(exit())")``.
126+
119127
Fixed ImagePath.Path array handling
120128
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
121129

src/PIL/ImageMath.py

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

249-
out = builtins.eval(expression, args)
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")
253+
254+
out = builtins.eval(expression, {"__builtins": {"abs": abs}}, args)
250255
try:
251256
return out.im
252257
except AttributeError:

0 commit comments

Comments
 (0)