From fbaaf3c19b0b27206205c7ce95e95db1190f227e Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 26 Feb 2022 16:30:44 +1100 Subject: [PATCH 1/7] Do not read data until necessary --- src/PIL/GbrImagePlugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/GbrImagePlugin.py b/src/PIL/GbrImagePlugin.py index 3d8fc47b224..4caeda8ef47 100644 --- a/src/PIL/GbrImagePlugin.py +++ b/src/PIL/GbrImagePlugin.py @@ -43,9 +43,9 @@ class GbrImageFile(ImageFile.ImageFile): def _open(self): header_size = i32(self.fp.read(4)) - version = i32(self.fp.read(4)) if header_size < 20: raise SyntaxError("not a GIMP brush") + version = i32(self.fp.read(4)) if version not in (1, 2): raise SyntaxError(f"Unsupported GIMP brush version: {version}") From efb9d503a755499fb9c705a5d05952e6f9398c43 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 26 Feb 2022 17:29:21 +1100 Subject: [PATCH 2/7] Raise SyntaxError if data is not as expected --- Tests/test_file_xbm.py | 9 ++++++++- src/PIL/XbmImagePlugin.py | 17 +++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Tests/test_file_xbm.py b/Tests/test_file_xbm.py index 487920a9282..9c54c675560 100644 --- a/Tests/test_file_xbm.py +++ b/Tests/test_file_xbm.py @@ -2,7 +2,7 @@ import pytest -from PIL import Image +from PIL import Image, XbmImagePlugin from .helper import hopper @@ -63,6 +63,13 @@ def test_open_filename_with_underscore(): assert im.size == (128, 128) +def test_invalid_file(): + invalid_file = "Tests/images/flower.jpg" + + with pytest.raises(SyntaxError): + XbmImagePlugin.XbmImageFile(invalid_file) + + def test_save_wrong_mode(tmp_path): im = hopper() out = str(tmp_path / "temp.xbm") diff --git a/src/PIL/XbmImagePlugin.py b/src/PIL/XbmImagePlugin.py index 644cfb39bc6..8aea0d60ce9 100644 --- a/src/PIL/XbmImagePlugin.py +++ b/src/PIL/XbmImagePlugin.py @@ -52,18 +52,19 @@ def _open(self): m = xbm_head.match(self.fp.read(512)) - if m: + if not m: + raise SyntaxError("not a XBM file") - xsize = int(m.group("width")) - ysize = int(m.group("height")) + xsize = int(m.group("width")) + ysize = int(m.group("height")) - if m.group("hotspot"): - self.info["hotspot"] = (int(m.group("xhot")), int(m.group("yhot"))) + if m.group("hotspot"): + self.info["hotspot"] = (int(m.group("xhot")), int(m.group("yhot"))) - self.mode = "1" - self._size = xsize, ysize + self.mode = "1" + self._size = xsize, ysize - self.tile = [("xbm", (0, 0) + self.size, m.end(), None)] + self.tile = [("xbm", (0, 0) + self.size, m.end(), None)] def _save(im, fp, filename): From 83b9e66133b0a2c105c92e682921f1de3b619c9b Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 26 Feb 2022 17:34:13 +1100 Subject: [PATCH 3/7] Moved flags check into _accept --- src/PIL/FliImagePlugin.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/PIL/FliImagePlugin.py b/src/PIL/FliImagePlugin.py index f2d4857f730..ea950330555 100644 --- a/src/PIL/FliImagePlugin.py +++ b/src/PIL/FliImagePlugin.py @@ -26,7 +26,11 @@ def _accept(prefix): - return len(prefix) >= 6 and i16(prefix, 4) in [0xAF11, 0xAF12] + return ( + len(prefix) >= 6 + and i16(prefix, 4) in [0xAF11, 0xAF12] + and i16(prefix, 14) in [0, 3] # flags + ) ## @@ -44,11 +48,7 @@ def _open(self): # HEAD s = self.fp.read(128) - if not ( - _accept(s) - and i16(s, 14) in [0, 3] # flags - and s[20:22] == b"\x00\x00" # reserved - ): + if not (_accept(s) and s[20:22] == b"\x00\x00"): raise SyntaxError("not an FLI/FLC file") # frames From 885e305fe97761fdfc7b3cab414ff995af76d605 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 26 Feb 2022 17:34:29 +1100 Subject: [PATCH 4/7] Make code clearer by matching _accept condition --- src/PIL/WmfImagePlugin.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/PIL/WmfImagePlugin.py b/src/PIL/WmfImagePlugin.py index c32cc52f8d0..2f54cdebbea 100644 --- a/src/PIL/WmfImagePlugin.py +++ b/src/PIL/WmfImagePlugin.py @@ -21,7 +21,6 @@ from . import Image, ImageFile from ._binary import i16le as word -from ._binary import i32le as dword from ._binary import si16le as short from ._binary import si32le as _long @@ -112,7 +111,7 @@ def _open(self): if s[22:26] != b"\x01\x00\t\x00": raise SyntaxError("Unsupported WMF file format") - elif dword(s) == 1 and s[40:44] == b" EMF": + elif s[:4] == b"\x01\x00\x00\x00" and s[40:44] == b" EMF": # enhanced metafile # get bounding box From e2288356caeb012d81e846b7ef9b6a29737dc037 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 27 Feb 2022 14:47:07 +1100 Subject: [PATCH 5/7] Use _accept check in _open --- Tests/test_file_dds.py | 7 +++++++ Tests/test_file_ftex.py | 7 +++++++ docs/example/DdsImagePlugin.py | 4 +++- src/PIL/DdsImagePlugin.py | 4 +++- src/PIL/FtexImagePlugin.py | 3 ++- 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Tests/test_file_dds.py b/Tests/test_file_dds.py index 2f46ed77e0c..58447122e58 100644 --- a/Tests/test_file_dds.py +++ b/Tests/test_file_dds.py @@ -196,6 +196,13 @@ def test__accept_false(): assert not output +def test_invalid_file(): + invalid_file = "Tests/images/flower.jpg" + + with pytest.raises(SyntaxError): + DdsImagePlugin.DdsImageFile(invalid_file) + + def test_short_header(): """Check a short header""" with open(TEST_FILE_DXT5, "rb") as f: diff --git a/Tests/test_file_ftex.py b/Tests/test_file_ftex.py index 5447dc7404f..cae20fa46eb 100644 --- a/Tests/test_file_ftex.py +++ b/Tests/test_file_ftex.py @@ -16,6 +16,13 @@ def test_load_dxt1(): assert_image_similar(im, target.convert("RGBA"), 15) +def test_invalid_file(): + invalid_file = "Tests/images/flower.jpg" + + with pytest.raises(SyntaxError): + FtexImagePlugin.FtexImageFile(invalid_file) + + def test_constants_deprecation(): for enum, prefix in { FtexImagePlugin.Format: "FORMAT_", diff --git a/docs/example/DdsImagePlugin.py b/docs/example/DdsImagePlugin.py index 272409416cc..29fefba1643 100644 --- a/docs/example/DdsImagePlugin.py +++ b/docs/example/DdsImagePlugin.py @@ -210,7 +210,9 @@ class DdsImageFile(ImageFile.ImageFile): format_description = "DirectDraw Surface" def _open(self): - magic, header_size = struct.unpack(" Date: Sat, 26 Feb 2022 17:53:27 +1100 Subject: [PATCH 6/7] Simplify code by using _accept --- src/PIL/IcnsImagePlugin.py | 2 +- src/PIL/TiffImagePlugin.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index 069aff96b63..c22bfe0ed06 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -167,7 +167,7 @@ def __init__(self, fobj): self.dct = dct = {} self.fobj = fobj sig, filesize = nextheader(fobj) - if sig != MAGIC: + if not _accept(sig): raise SyntaxError("not an icns file") i = HEADERSIZE while i < filesize: diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 35ff1c1bbf7..d8dc1741a3b 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -493,7 +493,7 @@ def __init__(self, ifh=b"II\052\0\0\0\0\0", prefix=None, group=None): endianness. :param prefix: Override the endianness of the file. """ - if ifh[:4] not in PREFIXES: + if not _accept(ifh): raise SyntaxError(f"not a TIFF file (header {repr(ifh)} not valid)") self._prefix = prefix if prefix is not None else ifh[:2] if self._prefix == MM: From 633abcbe7e9a1bf955abdd93f71085c55e25fece Mon Sep 17 00:00:00 2001 From: Andrew Murray <3112309+radarhere@users.noreply.github.com> Date: Sun, 6 Mar 2022 07:27:11 +1100 Subject: [PATCH 7/7] Updated error message Co-authored-by: Hugo van Kemenade --- src/PIL/FtexImagePlugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/FtexImagePlugin.py b/src/PIL/FtexImagePlugin.py index b264b7c5074..55d28e1ff64 100644 --- a/src/PIL/FtexImagePlugin.py +++ b/src/PIL/FtexImagePlugin.py @@ -95,7 +95,7 @@ class FtexImageFile(ImageFile.ImageFile): def _open(self): if not _accept(self.fp.read(4)): - raise SyntaxError("not a FTEX file") + raise SyntaxError("not an FTEX file") struct.unpack("