This commit is contained in:
wiredfool 2026-01-27 21:43:24 +00:00 committed by GitHub
commit 8c75d7a5e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 37 additions and 8 deletions

View File

@ -15,6 +15,7 @@ from .helper import (
assert_image_similar,
assert_image_similar_tofile,
hopper,
timeout_unless_slower_valgrind,
)
TEST_FILE_DXT1 = "Tests/images/dxt1-rgb-4bbp-noalpha_MipMaps-1.dds"
@ -540,3 +541,18 @@ def test_save_large_file(tmp_path: Path, pixel_format: str, mode: str) -> None:
im = hopper(mode).resize((440, 440))
# should not error in valgrind
im.save(tmp_path / "img.dds", pixel_format=pixel_format)
@timeout_unless_slower_valgrind(1)
@pytest.mark.parametrize(
"test_file",
[
"Tests/images/timeout-041dd17dfde800360a47a172269df127af138c6b.dds",
"Tests/images/timeout-755a4d204f4208e3597ac3391edebee196462bd0.dds",
"Tests/images/timeout-52d106579505547091ef69b58341351a37c23e31.dds",
"Tests/images/timeout-c60a3d7314213624607bfb3e38d551a8b24a7435.dds",
],
)
def test_timeout(test_file) -> None:
with Image.open(test_file) as im:
im.load()

View File

@ -503,21 +503,34 @@ class DdsRgbDecoder(ImageFile.PyDecoder):
while mask >> (offset + 1) << (offset + 1) == mask:
offset += 1
mask_offsets.append(offset)
mask_totals.append(mask >> offset)
mask_total = mask >> offset
if not mask_total:
mask_totals.append(0)
else:
mask_totals.append(255 / mask_total)
data = bytearray()
bytecount = bitcount // 8
dest_length = self.state.xsize * self.state.ysize * len(masks)
while len(data) < dest_length:
value = int.from_bytes(self.fd.read(bytecount), "little")
# consume the data
has_more = True
while len(data) < dest_length and has_more:
chunk = self.fd.read(bytecount)
# work around BufferedIO not being seekable
has_more = len(chunk) > 0
value = int.from_bytes(chunk, "little")
for i, mask in enumerate(masks):
masked_value = value & mask
# Remove the zero padding, and scale it to 8 bits
data += o8(
int(((masked_value >> mask_offsets[i]) / mask_totals[i]) * 255)
if mask_totals[i]
else 0
)
data += o8(int((masked_value >> mask_offsets[i]) * mask_totals[i]))
# extra padding pixels -- always all 0
if len(data) < dest_length:
pixel = bytearray()
pixel += o8(0)
ct_bytes = dest_length - len(data)
data += pixel * ct_bytes
self.set_as_raw(data)
return -1, 0