Fixed raising OSError in _safe_read when size is greater than SAFEBLOCK

This commit is contained in:
Andrew Murray 2021-12-07 11:40:44 +11:00
parent 81a3f68cf7
commit 5c05fe4d9b
2 changed files with 19 additions and 4 deletions

View File

@ -2,7 +2,7 @@ from io import BytesIO
import pytest import pytest
from PIL import EpsImagePlugin, Image, ImageFile, features from PIL import BmpImagePlugin, EpsImagePlugin, Image, ImageFile, _binary, features
from .helper import ( from .helper import (
assert_image, assert_image,
@ -111,6 +111,20 @@ class TestImageFile:
with pytest.raises(OSError): with pytest.raises(OSError):
p.close() p.close()
def test_truncated(self):
b = BytesIO(
b"BM000000000000" # head_data
+ _binary.o32le(
ImageFile.SAFEBLOCK + 1 + 4
) # header_size, so BmpImagePlugin will try to read SAFEBLOCK + 1 bytes
+ (
b"0" * ImageFile.SAFEBLOCK
) # only SAFEBLOCK bytes, so that the header is truncated
)
with pytest.raises(OSError) as e:
BmpImagePlugin.BmpImageFile(b)
assert str(e.value) == "Truncated File Read"
@skip_unless_feature("zlib") @skip_unless_feature("zlib")
def test_truncated_with_errors(self): def test_truncated_with_errors(self):
with Image.open("Tests/images/truncated_image.png") as im: with Image.open("Tests/images/truncated_image.png") as im:

View File

@ -545,12 +545,13 @@ def _safe_read(fp, size):
raise OSError("Truncated File Read") raise OSError("Truncated File Read")
return data return data
data = [] data = []
while size > 0: remaining_size = size
block = fp.read(min(size, SAFEBLOCK)) while remaining_size > 0:
block = fp.read(min(remaining_size, SAFEBLOCK))
if not block: if not block:
break break
data.append(block) data.append(block)
size -= len(block) remaining_size -= len(block)
if sum(len(d) for d in data) < size: if sum(len(d) for d in data) < size:
raise OSError("Truncated File Read") raise OSError("Truncated File Read")
return b"".join(data) return b"".join(data)