diff --git a/Tests/images/truncated_end_chunk.png b/Tests/images/truncated_end_chunk.png new file mode 100644 index 00000000000..5e88c5e4fa2 Binary files /dev/null and b/Tests/images/truncated_end_chunk.png differ diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py index 0f1d96365ea..c1a9f58f036 100644 --- a/Tests/test_file_png.py +++ b/Tests/test_file_png.py @@ -780,6 +780,18 @@ class MyStdOut: with Image.open(mystdout) as reloaded: assert_image_equal_tofile(reloaded, TEST_PNG_FILE) + def test_truncated_end_chunk(self) -> None: + with Image.open("Tests/images/truncated_end_chunk.png") as im: + with pytest.raises(OSError): + im.load() + + ImageFile.LOAD_TRUNCATED_IMAGES = True + try: + with Image.open("Tests/images/truncated_end_chunk.png") as im: + assert_image_equal_tofile(im, "Tests/images/hopper.png") + finally: + ImageFile.LOAD_TRUNCATED_IMAGES = False + @pytest.mark.skipif(is_win32(), reason="Requires Unix or macOS") @skip_unless_feature("zlib") diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py index 823f1249285..1248fb78529 100644 --- a/src/PIL/PngImagePlugin.py +++ b/src/PIL/PngImagePlugin.py @@ -981,7 +981,13 @@ def load_end(self): except EOFError: if cid == b"fdAT": length -= 4 - ImageFile._safe_read(self.fp, length) + try: + ImageFile._safe_read(self.fp, length) + except OSError as e: + if ImageFile.LOAD_TRUNCATED_IMAGES: + break + else: + raise e except AttributeError: logger.debug("%r %s %s (unknown)", cid, pos, length) s = ImageFile._safe_read(self.fp, length)