Skip to content

Commit b7668ef

Browse files
committed
Raise error in frombytes() if P;2L or P;4L data is truncated
1 parent 6a8de89 commit b7668ef

3 files changed

Lines changed: 28 additions & 0 deletions

File tree

Tests/test_file_pcx.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,16 @@ def test_break_padding(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
202202
for x in range(5):
203203
px[x, 3] = 0
204204
_test_buffer_overflow(tmp_path, im, monkeypatch)
205+
206+
207+
@pytest.mark.parametrize(
208+
"data_len, rawmode",
209+
(
210+
(5, "P;4L"),
211+
(3, "P;2L"),
212+
),
213+
)
214+
def test_truncated(data_len: int, rawmode: str) -> None:
215+
data = b"\x00" * data_len
216+
with pytest.raises(ValueError, match="not enough image data"):
217+
Image.frombuffer("P", (9, 1), data, "raw", rawmode, 0, 1)

Tests/test_image_array.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ def __init__(self, img: Image.Image, arr_params: dict[str, Any]) -> None:
6060
self.img = img
6161
self.__array_interface__ = arr_params
6262

63+
def __len__(self) -> int:
64+
return len(self.img.tobytes())
65+
6366
def tobytes(self) -> bytes:
6467
return self.img.tobytes()
6568

@@ -100,6 +103,9 @@ class Wrapper:
100103
def __init__(self, arr_params: dict[str, Any]) -> None:
101104
self.__array_interface__ = arr_params
102105

106+
def __len__(self) -> int:
107+
return 1
108+
103109
with pytest.raises(ValueError):
104110
wrapped = Wrapper({"shape": (1, 1), "strides": (1, 1), "typestr": "|u1"})
105111
Image.fromarray(wrapped, "L")

src/PIL/Image.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,12 @@ def frombytes(
943943
# may pass tuple instead of argument list
944944
decoder_args = decoder_args[0]
945945

946+
if decoder_args and decoder_args[0] in {"P;2L", "P;4L"}:
947+
multiple = 4 if decoder_args[0] == "P;2L" else 8
948+
if len(data) % multiple:
949+
msg = "not enough image data"
950+
raise ValueError(msg)
951+
946952
# default format
947953
if decoder_name == "raw" and decoder_args == ():
948954
decoder_args = self.mode
@@ -3350,6 +3356,9 @@ class SupportsArrayInterface(Protocol):
33503356
def __array_interface__(self) -> dict[str, Any]:
33513357
raise NotImplementedError()
33523358

3359+
def __len__(self) -> int:
3360+
raise NotImplementedError()
3361+
33533362

33543363
DecoderInput = bytes | bytearray | memoryview | SupportsArrayInterface
33553364

0 commit comments

Comments
 (0)