diff --git a/Tests/test_file_jpeg2k.py b/Tests/test_file_jpeg2k.py index 705dac880e5..6b58ec9a8a2 100644 --- a/Tests/test_file_jpeg2k.py +++ b/Tests/test_file_jpeg2k.py @@ -229,6 +229,19 @@ def test_header_errors() -> None: pass +@pytest.mark.parametrize("tbox", (b"", b"jp2h")) +def test_oversized_box_length(tbox: bytes) -> None: + # Do not raise an OverflowError() when seeking to the end of a box, + # or when reading the contents of a box + data = ( + b"\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a" # JP2 signature box + + struct.pack(">I4s", 1, tbox) # box with 64-bit length + + struct.pack(">Q", 2**63 - 12) # oversized length + ) + with pytest.raises(SyntaxError, match="Box length too large"): + Jpeg2KImagePlugin.Jpeg2KImageFile(BytesIO(data)) + + def test_layers_type(card: ImageFile.ImageFile, tmp_path: Path) -> None: outfile = tmp_path / "temp_layers.jp2" for quality_layers in [[100, 50, 10], (100, 50, 10), None]: diff --git a/src/PIL/Jpeg2KImagePlugin.py b/src/PIL/Jpeg2KImagePlugin.py index ca982f06aa5..7d27fcc8fff 100644 --- a/src/PIL/Jpeg2KImagePlugin.py +++ b/src/PIL/Jpeg2KImagePlugin.py @@ -54,6 +54,9 @@ def _read_bytes(self, num_bytes: int) -> bytes: if not self._can_read(num_bytes): msg = "Not enough data in header" raise SyntaxError(msg) + if self.fp.tell() + num_bytes >= 2**63: + msg = "Box length too large" + raise SyntaxError(msg) data = self.fp.read(num_bytes) if len(data) < num_bytes: @@ -83,6 +86,9 @@ def has_next_box(self) -> bool: def next_box_type(self) -> bytes: # Skip the rest of the box if it has not been read if self.remaining_in_box > 0: + if self.fp.tell() + self.remaining_in_box >= 2**63: + msg = "Box length too large" + raise SyntaxError(msg) self.fp.seek(self.remaining_in_box, os.SEEK_CUR) self.remaining_in_box = -1