From 5c05fe4d9b98e3c11b186c407d462249e85999bc Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 7 Dec 2021 11:40:44 +1100 Subject: [PATCH] Fixed raising OSError in _safe_read when size is greater than SAFEBLOCK --- Tests/test_imagefile.py | 16 +++++++++++++++- src/PIL/ImageFile.py | 7 ++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Tests/test_imagefile.py b/Tests/test_imagefile.py index f4e5a6a59..372cee8c0 100644 --- a/Tests/test_imagefile.py +++ b/Tests/test_imagefile.py @@ -2,7 +2,7 @@ from io import BytesIO import pytest -from PIL import EpsImagePlugin, Image, ImageFile, features +from PIL import BmpImagePlugin, EpsImagePlugin, Image, ImageFile, _binary, features from .helper import ( assert_image, @@ -111,6 +111,20 @@ class TestImageFile: with pytest.raises(OSError): 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") def test_truncated_with_errors(self): with Image.open("Tests/images/truncated_image.png") as im: diff --git a/src/PIL/ImageFile.py b/src/PIL/ImageFile.py index 453ed3e8c..d43667ca0 100644 --- a/src/PIL/ImageFile.py +++ b/src/PIL/ImageFile.py @@ -545,12 +545,13 @@ def _safe_read(fp, size): raise OSError("Truncated File Read") return data data = [] - while size > 0: - block = fp.read(min(size, SAFEBLOCK)) + remaining_size = size + while remaining_size > 0: + block = fp.read(min(remaining_size, SAFEBLOCK)) if not block: break data.append(block) - size -= len(block) + remaining_size -= len(block) if sum(len(d) for d in data) < size: raise OSError("Truncated File Read") return b"".join(data)