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
This commit is contained in:
Eric Soroos 2021-03-08 20:31:41 +01:00 committed by Hugo van Kemenade
parent 3bf5eddb89
commit 5a5e6db0ab
3 changed files with 18 additions and 5 deletions

View File

@ -1,5 +1,4 @@
import io
import pytest
from PIL import EpsImagePlugin, Image, features
@ -264,3 +263,17 @@ def test_emptyline():
assert image.mode == "RGB"
assert image.size == (460, 352)
assert image.format == "EPS"
@pytest.mark.timeout(timeout=5)
@pytest.mark.parametrize(
"test_file",
[
("Tests/images/timeout-d675703545fee17acab56e5fec644c19979175de.eps")
],
)
def test_timeout(test_file):
with open(test_file, "rb") as f:
with pytest.raises(Image.UnidentifiedImageError):
with Image.open(f):
pass

View File

@ -170,12 +170,12 @@ class PSFile:
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)
@ -183,7 +183,7 @@ class PSFile:
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):