diff --git a/Tests/test_imagefile.py b/Tests/test_imagefile.py index 6656ee506..2dcebc4b1 100644 --- a/Tests/test_imagefile.py +++ b/Tests/test_imagefile.py @@ -308,7 +308,20 @@ class TestPyDecoder(CodecsTest): assert MockPyDecoder.last.state.xsize == 200 assert MockPyDecoder.last.state.ysize == 200 - def test_negsize(self) -> None: + def test_negative_offset(self) -> None: + buf = BytesIO(b"\x00" * 255) + + im = MockImageFile(buf) + im.tile = [ImageFile._Tile("MOCK", (-10, yoff, xsize, ysize), 32, None)] + + with pytest.raises(ValueError): + im.load() + + im.tile = [ImageFile._Tile("MOCK", (xoff, -10, xsize, ysize), 32, None)] + with pytest.raises(ValueError): + im.load() + + def test_negative_size(self) -> None: buf = BytesIO(b"\x00" * 255) im = MockImageFile(buf) @@ -386,7 +399,39 @@ class TestPyEncoder(CodecsTest): assert MockPyEncoder.last.state.xsize == 200 assert MockPyEncoder.last.state.ysize == 200 - def test_negsize(self) -> None: + def test_negative_offset(self) -> None: + buf = BytesIO(b"\x00" * 255) + + im = MockImageFile(buf) + + fp = BytesIO() + MockPyEncoder.last = None + with pytest.raises(ValueError): + ImageFile._save( + im, + fp, + [ + ImageFile._Tile( + "MOCK", (-10, yoff, xoff + xsize, yoff + ysize), 0, "RGB" + ) + ], + ) + last: MockPyEncoder | None = MockPyEncoder.last + assert last + assert last.cleanup_called + + with pytest.raises(ValueError): + ImageFile._save( + im, + fp, + [ + ImageFile._Tile( + "MOCK", (xoff, -10, xoff + xsize, yoff + ysize), 0, "RGB" + ) + ], + ) + + def test_negative_size(self) -> None: buf = BytesIO(b"\x00" * 255) im = MockImageFile(buf) diff --git a/src/PIL/ImageFile.py b/src/PIL/ImageFile.py index b79f23f0d..dd1116ab9 100644 --- a/src/PIL/ImageFile.py +++ b/src/PIL/ImageFile.py @@ -805,6 +805,10 @@ class PyCodec: if extents: x0, y0, x1, y1 = extents + + if x0 < 0 or y0 < 0 or x1 > self.im.size[0] or y1 > self.im.size[1]: + msg = "Tile cannot extend outside image" + raise ValueError(msg) else: x0, y0, x1, y1 = (0, 0, 0, 0) @@ -820,13 +824,6 @@ class PyCodec: msg = "Size must be positive" raise ValueError(msg) - if ( - self.state.xsize + self.state.xoff > self.im.size[0] - or self.state.ysize + self.state.yoff > self.im.size[1] - ): - msg = "Tile cannot extend outside image" - raise ValueError(msg) - class PyDecoder(PyCodec): """