File 020-CVE-2021-28677.patch of Package python-Pillow
From 5a5e6db0abf4e7a638fb1b3408c4e495a096cb92 Mon Sep 17 00:00:00 2001
From: Eric Soroos <eric-github@soroos.net>
Date: Mon, 8 Mar 2021 20:31:41 +0100
Subject: [PATCH] Fix EPS DOS on _open -- CVE-2021-28677
* The readline used in EPS has to deal with any combination of \r and
\n as line endings. It used an accidentally quadratic method of
accumulating lines while looking for a line ending.
* A malicious EPS file could use this to perform a DOS of Pillow in
the open phase, before an image was accepted for opening.
* This dates to the PIL Fork
---
...675703545fee17acab56e5fec644c19979175de.eps | Bin 0 -> 549784 bytes
Tests/test_file_eps.py | 15 ++++++++++++++-
PIL/EpsImagePlugin.py | 8 ++++----
3 files changed, 18 insertions(+), 5 deletions(-)
create mode 100644 Tests/images/timeout-d675703545fee17acab56e5fec644c19979175de.eps
diff --git a/Tests/test_file_eps.py b/Tests/test_file_eps.py
index ea91375dadb..e616ffa0cf6 100644
--- a/Tests/test_file_eps.py
+++ b/Tests/test_file_eps.py
@@ -267,7 +267,15 @@ def test_open_eps(self):
# Assert
self.assertEqual(img.mode, "RGB")
+
+ # @pytest.mark.timeout(timeout=5) # not available in unittest
+ def test_timeout(self):
+ test_file = "Tests/images/timeout-d675703545fee17acab56e5fec644c19979175de.eps"
+ with open(test_file, "rb") as f:
+ with self.assertRaises(IOError):
+ with Image.open(f):
+ pass
if __name__ == '__main__':
unittest.main()
diff --git a/PIL/EpsImagePlugin.py b/PIL/EpsImagePlugin.py
index dc61f48edc9..3bf8ee0ab35 100644
--- a/PIL/EpsImagePlugin.py
+++ b/PIL/EpsImagePlugin.py
@@ -166,12 +166,12 @@ def seek(self, offset, whence=io.SEEK_SET):
self.fp.seek(offset, whence)
def readline(self):
- s = self.char or b""
+ s = [self.char or b""]
self.char = None
c = self.fp.read(1)
- while c not in b"\r\n":
- s = s + c
+ while (c not in b"\r\n") and len(c):
+ s.append(c)
c = self.fp.read(1)
self.char = self.fp.read(1)
@@ -179,7 +179,7 @@ def readline(self):
if self.char in b"\r\n":
self.char = None
- return s.decode('latin-1')
+ return b"".join(s).decode("latin-1")
def _accept(prefix):