Skip to content

Commit d12af6d

Browse files
authored
Raise ValueError if insufficient data is read from DDS RGB file (#9405)
2 parents be0b7ee + db45f79 commit d12af6d

6 files changed

Lines changed: 26 additions & 4 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
131 Bytes
Binary file not shown.

Tests/test_file_dds.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,3 +540,18 @@ def test_save_large_file(tmp_path: Path, pixel_format: str, mode: str) -> None:
540540
im = hopper(mode).resize((440, 440))
541541
# should not error in valgrind
542542
im.save(tmp_path / "img.dds", pixel_format=pixel_format)
543+
544+
545+
@pytest.mark.parametrize(
546+
"test_file",
547+
[
548+
"Tests/images/timeout-041dd17dfde800360a47a172269df127af138c6b.dds",
549+
"Tests/images/timeout-755a4d204f4208e3597ac3391edebee196462bd0.dds",
550+
"Tests/images/timeout-52d106579505547091ef69b58341351a37c23e31.dds",
551+
"Tests/images/timeout-c60a3d7314213624607bfb3e38d551a8b24a7435.dds",
552+
],
553+
)
554+
def test_not_enough_image_data(test_file: str) -> None:
555+
with Image.open(test_file) as im:
556+
with pytest.raises(ValueError, match="not enough image data"):
557+
im.load()

src/PIL/DdsImagePlugin.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -489,9 +489,14 @@ class DdsRgbDecoder(ImageFile.PyDecoder):
489489
_pulls_fd = True
490490

491491
def decode(self, buffer: Image.DecoderInput) -> tuple[int, int]:
492-
assert self.fd is not None
493492
bitcount, masks = self.args
494493

494+
data = bytearray()
495+
bytecount = bitcount // 8
496+
if not bytecount:
497+
self.set_as_raw(data)
498+
return -1, 0
499+
495500
# Some masks will be padded with zeros, e.g. R 0b11 G 0b1100
496501
# Calculate how many zeros each mask is padded with
497502
mask_offsets = []
@@ -505,11 +510,13 @@ def decode(self, buffer: Image.DecoderInput) -> tuple[int, int]:
505510
mask_offsets.append(offset)
506511
mask_totals.append(mask >> offset)
507512

508-
data = bytearray()
509-
bytecount = bitcount // 8
513+
assert self.fd is not None
510514
dest_length = self.state.xsize * self.state.ysize * len(masks)
511515
while len(data) < dest_length:
512-
value = int.from_bytes(self.fd.read(bytecount), "little")
516+
bytes_read = self.fd.read(bytecount)
517+
if len(bytes_read) < bytecount:
518+
break
519+
value = int.from_bytes(bytes_read, "little")
513520
for i, mask in enumerate(masks):
514521
masked_value = value & mask
515522
# Remove the zero padding, and scale it to 8 bits

0 commit comments

Comments
 (0)