From ab708dac7196a0090b77bbaa2daecd88953a2cb7 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 23 Dec 2024 10:56:36 +1100 Subject: [PATCH] Assert fp is not None --- Tests/test_file_bufrstub.py | 1 + Tests/test_file_cur.py | 1 + Tests/test_file_gribstub.py | 1 + Tests/test_file_hdf5stub.py | 1 + Tests/test_file_jpeg.py | 3 ++- Tests/test_file_libtiff.py | 13 +++++++++++-- Tests/test_file_tiff.py | 5 ++++- Tests/test_image_load.py | 1 + docs/example/DdsImagePlugin.py | 1 + src/PIL/BlpImagePlugin.py | 1 + src/PIL/BmpImagePlugin.py | 2 ++ src/PIL/BufrStubImagePlugin.py | 1 + src/PIL/CurImagePlugin.py | 1 + src/PIL/DcxImagePlugin.py | 1 + src/PIL/DdsImagePlugin.py | 1 + src/PIL/EpsImagePlugin.py | 2 ++ src/PIL/FliImagePlugin.py | 2 ++ src/PIL/FpxImagePlugin.py | 2 ++ src/PIL/FtexImagePlugin.py | 1 + src/PIL/GbrImagePlugin.py | 2 ++ src/PIL/GifImagePlugin.py | 2 ++ src/PIL/GribStubImagePlugin.py | 1 + src/PIL/Hdf5StubImagePlugin.py | 1 + src/PIL/IcnsImagePlugin.py | 1 + src/PIL/IcoImagePlugin.py | 1 + src/PIL/ImImagePlugin.py | 1 + src/PIL/ImageFile.py | 1 + src/PIL/IptcImagePlugin.py | 3 +++ src/PIL/Jpeg2KImagePlugin.py | 2 ++ src/PIL/JpegImagePlugin.py | 7 +++++++ src/PIL/MicImagePlugin.py | 1 + src/PIL/MpoImagePlugin.py | 2 ++ src/PIL/PngImagePlugin.py | 3 +++ src/PIL/PsdImagePlugin.py | 1 + src/PIL/QoiImagePlugin.py | 1 + src/PIL/SpiderImagePlugin.py | 1 + src/PIL/TiffImagePlugin.py | 2 ++ src/PIL/WalImageFile.py | 2 ++ src/PIL/WebPImagePlugin.py | 1 + src/PIL/WmfImagePlugin.py | 2 ++ src/PIL/XpmImagePlugin.py | 2 ++ 41 files changed, 77 insertions(+), 4 deletions(-) diff --git a/Tests/test_file_bufrstub.py b/Tests/test_file_bufrstub.py index 77ee5b0ea..983eb381c 100644 --- a/Tests/test_file_bufrstub.py +++ b/Tests/test_file_bufrstub.py @@ -61,6 +61,7 @@ def test_handler(tmp_path: Path) -> None: def load(self, im: ImageFile.StubImageFile) -> Image.Image: self.loaded = True + assert im.fp is not None im.fp.close() return Image.new("RGB", (1, 1)) diff --git a/Tests/test_file_cur.py b/Tests/test_file_cur.py index dbf1b866d..ff82e2983 100644 --- a/Tests/test_file_cur.py +++ b/Tests/test_file_cur.py @@ -26,6 +26,7 @@ def test_invalid_file() -> None: no_cursors_file = "Tests/images/no_cursors.cur" cur = CurImagePlugin.CurImageFile(TEST_FILE) + assert cur.fp is not None cur.fp.close() with open(no_cursors_file, "rb") as cur.fp: with pytest.raises(TypeError): diff --git a/Tests/test_file_gribstub.py b/Tests/test_file_gribstub.py index aba473d24..71cce68b1 100644 --- a/Tests/test_file_gribstub.py +++ b/Tests/test_file_gribstub.py @@ -61,6 +61,7 @@ def test_handler(tmp_path: Path) -> None: def load(self, im: Image.Image) -> Image.Image: self.loaded = True + assert im.fp is not None im.fp.close() return Image.new("RGB", (1, 1)) diff --git a/Tests/test_file_hdf5stub.py b/Tests/test_file_hdf5stub.py index 8275bd0d8..ccd937f4e 100644 --- a/Tests/test_file_hdf5stub.py +++ b/Tests/test_file_hdf5stub.py @@ -63,6 +63,7 @@ def test_handler(tmp_path: Path) -> None: def load(self, im: Image.Image) -> Image.Image: self.loaded = True + assert im.fp is not None im.fp.close() return Image.new("RGB", (1, 1)) diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index 347a162a5..3dd7da959 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -1085,8 +1085,9 @@ class TestFileCloseW32: im.save(tmpfile) im = Image.open(tmpfile) + assert im.fp is not None + assert not im.fp.closed fp = im.fp - assert not fp.closed with pytest.raises(OSError): os.remove(tmpfile) im.load() diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 9c49b1534..2a87e60c8 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -11,7 +11,15 @@ from typing import Any, NamedTuple import pytest -from PIL import Image, ImageFilter, ImageOps, TiffImagePlugin, TiffTags, features +from PIL import ( + Image, + ImageFile, + ImageFilter, + ImageOps, + TiffImagePlugin, + TiffTags, + features, +) from PIL.TiffImagePlugin import OSUBFILETYPE, SAMPLEFORMAT, STRIPOFFSETS, SUBIFD from .helper import ( @@ -556,8 +564,9 @@ class TestFileLibTiff(LibTiffTestCase): im.save(out, compression=compression) def test_fp_leak(self) -> None: - im: Image.Image | None = Image.open("Tests/images/hopper_g4_500.tif") + im: ImageFile.ImageFile | None = Image.open("Tests/images/hopper_g4_500.tif") assert im is not None + assert im.fp is not None fn = im.fp.fileno() os.fstat(fn) diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 6f51d4651..cfeb55c7e 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -861,6 +861,7 @@ class TestFileTiff: im = Image.open(tmpfile) fp = im.fp + assert fp is not None assert not fp.closed im.load() assert fp.closed @@ -874,6 +875,7 @@ class TestFileTiff: with open(tmpfile, "rb") as f: im = Image.open(f) fp = im.fp + assert fp is not None assert not fp.closed im.load() assert not fp.closed @@ -925,8 +927,9 @@ class TestFileTiffW32: im.save(tmpfile) im = Image.open(tmpfile) + assert im.fp is not None + assert not im.fp.closed fp = im.fp - assert not fp.closed with pytest.raises(OSError): os.remove(tmpfile) im.load() diff --git a/Tests/test_image_load.py b/Tests/test_image_load.py index 4f1d63b8f..1d5f0d17c 100644 --- a/Tests/test_image_load.py +++ b/Tests/test_image_load.py @@ -38,6 +38,7 @@ def test_close_after_load(caplog: pytest.LogCaptureFixture) -> None: def test_contextmanager() -> None: fn = None with Image.open("Tests/images/hopper.gif") as im: + assert im.fp is not None fn = im.fp.fileno() os.fstat(fn) diff --git a/docs/example/DdsImagePlugin.py b/docs/example/DdsImagePlugin.py index 10828bff0..b464ae58d 100644 --- a/docs/example/DdsImagePlugin.py +++ b/docs/example/DdsImagePlugin.py @@ -213,6 +213,7 @@ class DdsImageFile(ImageFile.ImageFile): format_description = "DirectDraw Surface" def _open(self) -> None: + assert self.fp is not None if not _accept(self.fp.read(4)): msg = "not a DDS file" raise SyntaxError(msg) diff --git a/src/PIL/BlpImagePlugin.py b/src/PIL/BlpImagePlugin.py index e5605635e..aa9ba9e27 100644 --- a/src/PIL/BlpImagePlugin.py +++ b/src/PIL/BlpImagePlugin.py @@ -258,6 +258,7 @@ class BlpImageFile(ImageFile.ImageFile): format_description = "Blizzard Mipmap Format" def _open(self) -> None: + assert self.fp is not None self.magic = self.fp.read(4) self.fp.seek(5, os.SEEK_CUR) diff --git a/src/PIL/BmpImagePlugin.py b/src/PIL/BmpImagePlugin.py index bf8f29577..45b608d85 100644 --- a/src/PIL/BmpImagePlugin.py +++ b/src/PIL/BmpImagePlugin.py @@ -74,6 +74,7 @@ class BmpImageFile(ImageFile.ImageFile): def _bitmap(self, header: int = 0, offset: int = 0) -> None: """Read relevant info about the BMP""" + assert self.fp is not None read, seek = self.fp.read, self.fp.seek if header: seek(header) @@ -307,6 +308,7 @@ class BmpImageFile(ImageFile.ImageFile): def _open(self) -> None: """Open file, check magic number and read header""" # read 14 bytes: magic number, filesize, reserved, header final offset + assert self.fp is not None head_data = self.fp.read(14) # choke if the file does not have the required magic bytes if not _accept(head_data): diff --git a/src/PIL/BufrStubImagePlugin.py b/src/PIL/BufrStubImagePlugin.py index 0ee2f653b..521e5defd 100644 --- a/src/PIL/BufrStubImagePlugin.py +++ b/src/PIL/BufrStubImagePlugin.py @@ -40,6 +40,7 @@ class BufrStubImageFile(ImageFile.StubImageFile): format_description = "BUFR" def _open(self) -> None: + assert self.fp is not None offset = self.fp.tell() if not _accept(self.fp.read(4)): diff --git a/src/PIL/CurImagePlugin.py b/src/PIL/CurImagePlugin.py index c4be0ceca..4688a30f7 100644 --- a/src/PIL/CurImagePlugin.py +++ b/src/PIL/CurImagePlugin.py @@ -38,6 +38,7 @@ class CurImageFile(BmpImagePlugin.BmpImageFile): format_description = "Windows Cursor" def _open(self) -> None: + assert self.fp is not None offset = self.fp.tell() # check magic diff --git a/src/PIL/DcxImagePlugin.py b/src/PIL/DcxImagePlugin.py index f67f27d73..e4ee6989f 100644 --- a/src/PIL/DcxImagePlugin.py +++ b/src/PIL/DcxImagePlugin.py @@ -44,6 +44,7 @@ class DcxImageFile(PcxImageFile): def _open(self) -> None: # Header + assert self.fp is not None s = self.fp.read(4) if not _accept(s): msg = "not a DCX file" diff --git a/src/PIL/DdsImagePlugin.py b/src/PIL/DdsImagePlugin.py index 1b6408237..540d12ad6 100644 --- a/src/PIL/DdsImagePlugin.py +++ b/src/PIL/DdsImagePlugin.py @@ -333,6 +333,7 @@ class DdsImageFile(ImageFile.ImageFile): format_description = "DirectDraw Surface" def _open(self) -> None: + assert self.fp is not None if not _accept(self.fp.read(4)): msg = "not a DDS file" raise SyntaxError(msg) diff --git a/src/PIL/EpsImagePlugin.py b/src/PIL/EpsImagePlugin.py index fb1e301c0..7d6cc1ff2 100644 --- a/src/PIL/EpsImagePlugin.py +++ b/src/PIL/EpsImagePlugin.py @@ -187,6 +187,7 @@ class EpsImageFile(ImageFile.ImageFile): mode_map = {1: "L", 2: "LAB", 3: "RGB", 4: "CMYK"} def _open(self) -> None: + assert self.fp is not None (length, offset) = self._find_offset(self.fp) # go to offset - start of "%!PS" @@ -398,6 +399,7 @@ class EpsImageFile(ImageFile.ImageFile): ) -> Image.core.PixelAccess | None: # Load EPS via Ghostscript if self.tile: + assert self.fp is not None self.im = Ghostscript(self.tile, self.size, self.fp, scale, transparency) self._mode = self.im.mode self._size = self.im.size diff --git a/src/PIL/FliImagePlugin.py b/src/PIL/FliImagePlugin.py index 666390be9..f15cf5973 100644 --- a/src/PIL/FliImagePlugin.py +++ b/src/PIL/FliImagePlugin.py @@ -47,6 +47,7 @@ class FliImageFile(ImageFile.ImageFile): def _open(self) -> None: # HEAD + assert self.fp is not None s = self.fp.read(128) if not (_accept(s) and s[20:22] == b"\x00\x00"): msg = "not an FLI/FLC file" @@ -110,6 +111,7 @@ class FliImageFile(ImageFile.ImageFile): # load palette i = 0 + assert self.fp is not None for e in range(i16(self.fp.read(2))): s = self.fp.read(2) i = i + s[0] diff --git a/src/PIL/FpxImagePlugin.py b/src/PIL/FpxImagePlugin.py index 8fef51076..d650be026 100644 --- a/src/PIL/FpxImagePlugin.py +++ b/src/PIL/FpxImagePlugin.py @@ -58,6 +58,7 @@ class FpxImageFile(ImageFile.ImageFile): # read the OLE directory and see if this is a likely # to be a FlashPix file + assert self.fp is not None try: self.ole = olefile.OleFileIO(self.fp) except OSError as e: @@ -229,6 +230,7 @@ class FpxImageFile(ImageFile.ImageFile): if y >= ysize: break # isn't really required + assert self.fp is not None self.stream = stream self._fp = self.fp self.fp = None diff --git a/src/PIL/FtexImagePlugin.py b/src/PIL/FtexImagePlugin.py index ddb469bc3..a875a097f 100644 --- a/src/PIL/FtexImagePlugin.py +++ b/src/PIL/FtexImagePlugin.py @@ -72,6 +72,7 @@ class FtexImageFile(ImageFile.ImageFile): format_description = "Texture File Format (IW2:EOC)" def _open(self) -> None: + assert self.fp is not None if not _accept(self.fp.read(4)): msg = "not an FTEX file" raise SyntaxError(msg) diff --git a/src/PIL/GbrImagePlugin.py b/src/PIL/GbrImagePlugin.py index f319d7e84..556310bd6 100644 --- a/src/PIL/GbrImagePlugin.py +++ b/src/PIL/GbrImagePlugin.py @@ -42,6 +42,7 @@ class GbrImageFile(ImageFile.ImageFile): format_description = "GIMP brush file" def _open(self) -> None: + assert self.fp is not None header_size = i32(self.fp.read(4)) if header_size < 20: msg = "not a GIMP brush" @@ -90,6 +91,7 @@ class GbrImageFile(ImageFile.ImageFile): def load(self) -> Image.core.PixelAccess | None: if self._im is None: + assert self.fp is not None self.im = Image.core.new(self.mode, self.size) self.frombytes(self.fp.read(self._data_size)) return Image.Image.load(self) diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 47022d584..3ecd8fc0c 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -83,6 +83,7 @@ class GifImageFile(ImageFile.ImageFile): global_palette = None def data(self) -> bytes | None: + assert self.fp is not None s = self.fp.read(1) if s and s[0]: return self.fp.read(s[0]) @@ -96,6 +97,7 @@ class GifImageFile(ImageFile.ImageFile): def _open(self) -> None: # Screen + assert self.fp is not None s = self.fp.read(13) if not _accept(s): msg = "not a GIF file" diff --git a/src/PIL/GribStubImagePlugin.py b/src/PIL/GribStubImagePlugin.py index e9aa084b2..63ec390ae 100644 --- a/src/PIL/GribStubImagePlugin.py +++ b/src/PIL/GribStubImagePlugin.py @@ -40,6 +40,7 @@ class GribStubImageFile(ImageFile.StubImageFile): format_description = "GRIB" def _open(self) -> None: + assert self.fp is not None offset = self.fp.tell() if not _accept(self.fp.read(8)): diff --git a/src/PIL/Hdf5StubImagePlugin.py b/src/PIL/Hdf5StubImagePlugin.py index cc9e73deb..b3e73064f 100644 --- a/src/PIL/Hdf5StubImagePlugin.py +++ b/src/PIL/Hdf5StubImagePlugin.py @@ -40,6 +40,7 @@ class HDF5StubImageFile(ImageFile.StubImageFile): format_description = "HDF5" def _open(self) -> None: + assert self.fp is not None offset = self.fp.tell() if not _accept(self.fp.read(8)): diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index 9757b2b14..d57129a3d 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -267,6 +267,7 @@ class IcnsImageFile(ImageFile.ImageFile): format_description = "Mac OS icns resource" def _open(self) -> None: + assert self.fp is not None self.icns = IcnsFile(self.fp) self._mode = "RGBA" self.info["sizes"] = self.icns.itersizes() diff --git a/src/PIL/IcoImagePlugin.py b/src/PIL/IcoImagePlugin.py index e879f1801..2eb12f86a 100644 --- a/src/PIL/IcoImagePlugin.py +++ b/src/PIL/IcoImagePlugin.py @@ -326,6 +326,7 @@ class IcoImageFile(ImageFile.ImageFile): format_description = "Windows Icon" def _open(self) -> None: + assert self.fp is not None self.ico = IcoFile(self.fp) self.info["sizes"] = self.ico.sizes() self.size = self.ico.entry[0].dim diff --git a/src/PIL/ImImagePlugin.py b/src/PIL/ImImagePlugin.py index b4215a0b1..3b5ef2174 100644 --- a/src/PIL/ImImagePlugin.py +++ b/src/PIL/ImImagePlugin.py @@ -124,6 +124,7 @@ class ImImageFile(ImageFile.ImageFile): # Quick rejection: if there's not an LF among the first # 100 bytes, this is (probably) not a text header. + assert self.fp is not None if b"\n" not in self.fp.read(100): msg = "not an IM file" raise SyntaxError(msg) diff --git a/src/PIL/ImageFile.py b/src/PIL/ImageFile.py index 9836cd688..a5857d874 100644 --- a/src/PIL/ImageFile.py +++ b/src/PIL/ImageFile.py @@ -199,6 +199,7 @@ class ImageFile(Image.Image): # As of pypy 2.1.0, memory mapping was failing here. use_mmap = use_mmap and not hasattr(sys, "pypy_version_info") + assert self.fp is not None readonly = 0 # look for read/seek overrides diff --git a/src/PIL/IptcImagePlugin.py b/src/PIL/IptcImagePlugin.py index 60ab7c83f..894aabb18 100644 --- a/src/PIL/IptcImagePlugin.py +++ b/src/PIL/IptcImagePlugin.py @@ -77,6 +77,7 @@ class IptcImageFile(ImageFile.ImageFile): def field(self) -> tuple[tuple[int, int] | None, int]: # # get a IPTC field header + assert self.fp is not None s = self.fp.read(5) if not s.strip(b"\x00"): return None, 0 @@ -104,6 +105,7 @@ class IptcImageFile(ImageFile.ImageFile): def _open(self) -> None: # load descriptive fields + assert self.fp is not None while True: offset = self.fp.tell() tag, size = self.field() @@ -157,6 +159,7 @@ class IptcImageFile(ImageFile.ImageFile): offset, compression = self.tile[0][2:] + assert self.fp is not None self.fp.seek(offset) # Copy image data to temporary file diff --git a/src/PIL/Jpeg2KImagePlugin.py b/src/PIL/Jpeg2KImagePlugin.py index b6ebd562b..f4bb9c445 100644 --- a/src/PIL/Jpeg2KImagePlugin.py +++ b/src/PIL/Jpeg2KImagePlugin.py @@ -248,6 +248,7 @@ class Jpeg2KImageFile(ImageFile.ImageFile): format_description = "JPEG 2000 (ISO 15444)" def _open(self) -> None: + assert self.fp is not None sig = self.fp.read(4) if sig == b"\xff\x4f\xff\x51": self.codec = "j2k" @@ -296,6 +297,7 @@ class Jpeg2KImageFile(ImageFile.ImageFile): ] def _parse_comment(self) -> None: + assert self.fp is not None hdr = self.fp.read(2) length = _binary.i16be(hdr) self.fp.seek(length - 2, os.SEEK_CUR) diff --git a/src/PIL/JpegImagePlugin.py b/src/PIL/JpegImagePlugin.py index ab6a2f497..bcbee6940 100644 --- a/src/PIL/JpegImagePlugin.py +++ b/src/PIL/JpegImagePlugin.py @@ -60,6 +60,7 @@ if TYPE_CHECKING: def Skip(self: JpegImageFile, marker: int) -> None: + assert self.fp is not None n = i16(self.fp.read(2)) - 2 ImageFile._safe_read(self.fp, n) @@ -69,6 +70,7 @@ def APP(self: JpegImageFile, marker: int) -> None: # Application marker. Store these in the APP dictionary. # Also look for well-known application markers. + assert self.fp is not None n = i16(self.fp.read(2)) - 2 s = ImageFile._safe_read(self.fp, n) @@ -170,6 +172,7 @@ def APP(self: JpegImageFile, marker: int) -> None: def COM(self: JpegImageFile, marker: int) -> None: # # Comment marker. Store these in the APP dictionary. + assert self.fp is not None n = i16(self.fp.read(2)) - 2 s = ImageFile._safe_read(self.fp, n) @@ -186,6 +189,7 @@ def SOF(self: JpegImageFile, marker: int) -> None: # mode. Note that this could be made a bit brighter, by # looking for JFIF and Adobe APP markers. + assert self.fp is not None n = i16(self.fp.read(2)) - 2 s = ImageFile._safe_read(self.fp, n) self._size = i16(s, 3), i16(s, 1) @@ -234,6 +238,7 @@ def DQT(self: JpegImageFile, marker: int) -> None: # FIXME: The quantization tables can be used to estimate the # compression quality. + assert self.fp is not None n = i16(self.fp.read(2)) - 2 s = ImageFile._safe_read(self.fp, n) while len(s): @@ -334,6 +339,7 @@ class JpegImageFile(ImageFile.ImageFile): format_description = "JPEG (ISO 10918)" def _open(self) -> None: + assert self.fp is not None s = self.fp.read(3) if not _accept(s): @@ -401,6 +407,7 @@ class JpegImageFile(ImageFile.ImageFile): For premature EOF and LOAD_TRUNCATED_IMAGES adds EOI marker so libjpeg can finish decoding """ + assert self.fp is not None s = self.fp.read(read_bytes) if not s and ImageFile.LOAD_TRUNCATED_IMAGES and not hasattr(self, "_ended"): diff --git a/src/PIL/MicImagePlugin.py b/src/PIL/MicImagePlugin.py index 5f23a34b9..ba5daaafc 100644 --- a/src/PIL/MicImagePlugin.py +++ b/src/PIL/MicImagePlugin.py @@ -67,6 +67,7 @@ class MicImageFile(TiffImagePlugin.TiffImageFile): self._n_frames = len(self.images) self.is_animated = self._n_frames > 1 + assert self.fp is not None self.__fp = self.fp self.seek(0) diff --git a/src/PIL/MpoImagePlugin.py b/src/PIL/MpoImagePlugin.py index 71f89a09a..5e56b47b6 100644 --- a/src/PIL/MpoImagePlugin.py +++ b/src/PIL/MpoImagePlugin.py @@ -98,6 +98,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): _close_exclusive_fp_after_loading = False def _open(self) -> None: + assert self.fp is not None self.fp.seek(0) # prep the fp in order to pass the JPEG test JpegImagePlugin.JpegImageFile._open(self) self._after_jpeg_open() @@ -117,6 +118,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile): assert self.n_frames == len(self.__mpoffsets) del self.info["mpoffset"] # no longer needed self.is_animated = self.n_frames > 1 + assert self.fp is not None self._fp = self.fp # FIXME: hack self._fp.seek(self.__mpoffsets[0]) # get ready to read first frame self.__frame = 0 diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index 4b97992a3..b71b115d5 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -752,6 +752,7 @@ class PngImageFile(ImageFile.ImageFile): format_description = "Portable network graphics" def _open(self) -> None: + assert self.fp is not None if not _accept(self.fp.read(8)): msg = "not a PNG file" raise SyntaxError(msg) @@ -981,6 +982,7 @@ class PngImageFile(ImageFile.ImageFile): """internal: read more image data""" assert self.png is not None + assert self.fp is not None while self.__idat == 0: # end of chunk, skip forward to next one @@ -1014,6 +1016,7 @@ class PngImageFile(ImageFile.ImageFile): def load_end(self) -> None: """internal: finished reading image data""" assert self.png is not None + assert self.fp is not None if self.__idat != 0: self.fp.read(self.__idat) while True: diff --git a/src/PIL/PsdImagePlugin.py b/src/PIL/PsdImagePlugin.py index 8ff5e3908..e36ac8b42 100644 --- a/src/PIL/PsdImagePlugin.py +++ b/src/PIL/PsdImagePlugin.py @@ -60,6 +60,7 @@ class PsdImageFile(ImageFile.ImageFile): _close_exclusive_fp_after_loading = False def _open(self) -> None: + assert self.fp is not None read = self.fp.read # diff --git a/src/PIL/QoiImagePlugin.py b/src/PIL/QoiImagePlugin.py index 010d3f941..37590f3d3 100644 --- a/src/PIL/QoiImagePlugin.py +++ b/src/PIL/QoiImagePlugin.py @@ -22,6 +22,7 @@ class QoiImageFile(ImageFile.ImageFile): format_description = "Quite OK Image" def _open(self) -> None: + assert self.fp is not None if not _accept(self.fp.read(4)): msg = "not a QOI file" raise SyntaxError(msg) diff --git a/src/PIL/SpiderImagePlugin.py b/src/PIL/SpiderImagePlugin.py index 075073f9f..8778df736 100644 --- a/src/PIL/SpiderImagePlugin.py +++ b/src/PIL/SpiderImagePlugin.py @@ -101,6 +101,7 @@ class SpiderImageFile(ImageFile.ImageFile): def _open(self) -> None: # check header n = 27 * 4 # read 27 float values + assert self.fp is not None f = self.fp.read(n) try: diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index be4a57b74..1bd886f26 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -1168,6 +1168,7 @@ class TiffImageFile(ImageFile.ImageFile): """Open the first image in a TIFF file""" # Header + assert self.fp is not None ifh = self.fp.read(8) if ifh[2] == 43: ifh += self.fp.read(8) @@ -1328,6 +1329,7 @@ class TiffImageFile(ImageFile.ImageFile): # To be nice on memory footprint, if there's a # file descriptor, use that instead of reading # into a string in python. + assert self.fp is not None try: fp = hasattr(self.fp, "fileno") and self.fp.fileno() # flush the file descriptor, prevents error on pypy 2.4+ diff --git a/src/PIL/WalImageFile.py b/src/PIL/WalImageFile.py index 87e32878b..7e967ff14 100644 --- a/src/PIL/WalImageFile.py +++ b/src/PIL/WalImageFile.py @@ -39,6 +39,7 @@ class WalImageFile(ImageFile.ImageFile): self._mode = "P" # read header fields + assert self.fp is not None header = self.fp.read(32 + 24 + 32 + 12) self._size = i32(header, 32), i32(header, 36) Image._decompression_bomb_check(self.size) @@ -55,6 +56,7 @@ class WalImageFile(ImageFile.ImageFile): def load(self) -> Image.core.PixelAccess | None: if self._im is None: + assert self.fp is not None self.im = Image.core.new(self.mode, self.size) self.frombytes(self.fp.read(self.size[0] * self.size[1])) self.putpalette(quake2palette) diff --git a/src/PIL/WebPImagePlugin.py b/src/PIL/WebPImagePlugin.py index c7f855527..1e360d044 100644 --- a/src/PIL/WebPImagePlugin.py +++ b/src/PIL/WebPImagePlugin.py @@ -43,6 +43,7 @@ class WebPImageFile(ImageFile.ImageFile): def _open(self) -> None: # Use the newer AnimDecoder API to parse the (possibly) animated file, # and access muxed chunks like ICC/EXIF/XMP. + assert self.fp is not None self._decoder = _webp.WebPAnimDecoder(self.fp.read()) # Get info from decoder diff --git a/src/PIL/WmfImagePlugin.py b/src/PIL/WmfImagePlugin.py index 48e9823e8..e77d51f04 100644 --- a/src/PIL/WmfImagePlugin.py +++ b/src/PIL/WmfImagePlugin.py @@ -49,6 +49,7 @@ if hasattr(Image.core, "drawwmf"): self.bbox = im.info["wmf_bbox"] def load(self, im: ImageFile.StubImageFile) -> Image.Image: + assert im.fp is not None im.fp.seek(0) # rewind return Image.frombytes( "RGB", @@ -85,6 +86,7 @@ class WmfStubImageFile(ImageFile.StubImageFile): self._inch = None # check placable header + assert self.fp is not None s = self.fp.read(80) if s[:6] == b"\xd7\xcd\xc6\x9a\x00\x00": diff --git a/src/PIL/XpmImagePlugin.py b/src/PIL/XpmImagePlugin.py index 1fc6c0c39..a17b75d54 100644 --- a/src/PIL/XpmImagePlugin.py +++ b/src/PIL/XpmImagePlugin.py @@ -37,6 +37,7 @@ class XpmImageFile(ImageFile.ImageFile): format_description = "X11 Pixel Map" def _open(self) -> None: + assert self.fp is not None if not _accept(self.fp.read(9)): msg = "not an XPM file" raise SyntaxError(msg) @@ -111,6 +112,7 @@ class XpmImageFile(ImageFile.ImageFile): xsize, ysize = self.size + assert self.fp is not None s = [self.fp.readline()[1 : xsize + 1].ljust(xsize) for i in range(ysize)] return b"".join(s)