Package: pillow / 8.1.2+dfsg-0.3+deb11u2

CVE-2022-22817-2.patch Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
From: Andrew Murray <radarhere@users.noreply.github.com>
Date: Mon, 10 Jan 2022 21:49:55 +1100
X-Dgit-Generated: 8.1.2+dfsg-0.3+deb11u2 402664cf8c2ea7bb9353f52bca59171d42bdf330
Subject: Restrict builtins within lambdas for ImageMath.eval

(cherry picked from commit c930be0758ac02cf15a2b8d5409d50d443550581)

---

diff --git a/Tests/test_imagemath.py b/Tests/test_imagemath.py
index 239806796..09d5e1bc9 100644
--- a/Tests/test_imagemath.py
+++ b/Tests/test_imagemath.py
@@ -1,5 +1,7 @@
 from PIL import Image, ImageMath
 
+import pytest
+
 
 def pixel(im):
     if hasattr(im, "im"):
@@ -50,6 +52,19 @@ def test_ops():
     assert pixel(ImageMath.eval("float(B)**33", images)) == "F 8589934592.0"
 
 
+@pytest.mark.parametrize(
+    "expression",
+    (
+        "eval('pass')",
+        "(lambda: eval('pass'))()",
+        "(lambda: (lambda: eval('pass'))())()",
+    ),
+)
+def test_prevent_exec(expression):
+    with pytest.raises(ValueError):
+        ImageMath.eval(expression)
+
+
 def test_logical():
     assert pixel(ImageMath.eval("not A", images)) == 0
     assert pixel(ImageMath.eval("A and B", images)) == "L 2"
diff --git a/src/PIL/ImageMath.py b/src/PIL/ImageMath.py
index 06bea800d..47ad3c9ae 100644
--- a/src/PIL/ImageMath.py
+++ b/src/PIL/ImageMath.py
@@ -246,11 +246,18 @@ def eval(expression, _dict={}, **kw):
         if hasattr(v, "im"):
             args[k] = _Operand(v)
 
-    code = compile(expression, "<string>", "eval")
-    for name in code.co_names:
-        if name not in args and name != "abs":
-            raise ValueError(f"'{name}' not allowed")
+    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(f"'{name}' not allowed")
+
+    scan(compiled_code)
     out = builtins.eval(expression, {"__builtins": {"abs": abs}}, args)
     try:
         return out.im