diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index 2615f5a6028..2fc4e90ba7d 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -310,6 +310,14 @@ def test_roundtrip_save_all_1(tmp_path: Path) -> None: assert reloaded.getpixel((0, 0)) == 255 +@pytest.mark.parametrize("size", ((0, 1), (1, 0), (0, 0))) +def test_save_zero(size: tuple[int, int]) -> None: + b = BytesIO() + im = Image.new("RGB", size) + with pytest.raises(SystemError): + im.save(b, "GIF") + + @pytest.mark.parametrize( "path, mode", ( diff --git a/Tests/test_file_pcx.py b/Tests/test_file_pcx.py index 2e999eff6e1..60f71594b5d 100644 --- a/Tests/test_file_pcx.py +++ b/Tests/test_file_pcx.py @@ -37,6 +37,14 @@ def test_sanity(tmp_path: Path) -> None: im.save(f) +@pytest.mark.parametrize("size", ((0, 1), (1, 0), (0, 0))) +def test_save_zero(size: tuple[int, int]) -> None: + b = io.BytesIO() + im = Image.new("1", size) + with pytest.raises(ValueError): + im.save(b, "PCX") + + def test_p_4_planes() -> None: with Image.open("Tests/images/p_4_planes.pcx") as im: assert im.getpixel((0, 0)) == 3 diff --git a/Tests/test_file_spider.py b/Tests/test_file_spider.py index 3b3c3b4a518..c49cbae0c50 100644 --- a/Tests/test_file_spider.py +++ b/Tests/test_file_spider.py @@ -64,6 +64,14 @@ def test_save(tmp_path: Path) -> None: assert im2.format == "SPIDER" +@pytest.mark.parametrize("size", ((0, 1), (1, 0), (0, 0))) +def test_save_zero(size: tuple[int, int]) -> None: + b = BytesIO() + im = Image.new("1", size) + with pytest.raises(SystemError): + im.save(b, "SPIDER") + + def test_tempfile() -> None: # Arrange im = hopper() diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 76a0d4ab99f..390b3b374ab 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -937,7 +937,13 @@ def _get_optimize(im: Image.Image, info: dict[str, Any]) -> list[int] | None: :param info: encoderinfo :returns: list of indexes of palette entries in use, or None """ - if im.mode in ("P", "L") and info and info.get("optimize"): + if ( + im.mode in ("P", "L") + and info + and info.get("optimize") + and im.width != 0 + and im.height != 0 + ): # Potentially expensive operation. # The palette saves 3 bytes per color not used, but palette diff --git a/src/PIL/PcxImagePlugin.py b/src/PIL/PcxImagePlugin.py index 6b16d538537..3e34e3c63ba 100644 --- a/src/PIL/PcxImagePlugin.py +++ b/src/PIL/PcxImagePlugin.py @@ -146,6 +146,10 @@ def _open(self) -> None: def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None: + if im.width == 0 or im.height == 0: + msg = "Cannot write empty image as PCX" + raise ValueError(msg) + try: version, bits, planes, rawmode = SAVE[im.mode] except KeyError as e: diff --git a/src/PIL/SpiderImagePlugin.py b/src/PIL/SpiderImagePlugin.py index 8662922437e..0385064defd 100644 --- a/src/PIL/SpiderImagePlugin.py +++ b/src/PIL/SpiderImagePlugin.py @@ -244,7 +244,7 @@ def loadImageSeries(filelist: list[str] | None = None) -> list[Image.Image] | No def makeSpiderHeader(im: Image.Image) -> list[bytes]: nsam, nrow = im.size - lenbyt = nsam * 4 # There are labrec records in the header + lenbyt = max(1, nsam) * 4 # There are labrec records in the header labrec = int(1024 / lenbyt) if 1024 % lenbyt != 0: labrec += 1