Prevent DOS with large SAMPLESPERPIXEL in Tiff IFD

A large value in the SAMPLESPERPIXEL tag could lead to a memory and
runtime DOS in TiffImagePlugin.py when setting up the context for
image decoding.
This commit is contained in:
Eric Soroos 2022-10-28 14:11:25 +02:00 committed by Hugo van Kemenade
parent e055ef0356
commit 13f2c5ae14
3 changed files with 22 additions and 1 deletions

View File

@ -4,7 +4,7 @@ from io import BytesIO
import pytest
from PIL import Image, ImageFile, TiffImagePlugin
from PIL import Image, ImageFile, TiffImagePlugin, UnidentifiedImageError
from PIL.TiffImagePlugin import RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION
from .helper import (
@ -858,6 +858,19 @@ class TestFileTiff:
im.load()
ImageFile.LOAD_TRUNCATED_IMAGES = False
@pytest.mark.parametrize(
"test_file",
[
"Tests/images/oom-225817ca0f8c663be7ab4b9e717b02c661e66834.tif",
],
)
@pytest.mark.timeout(2)
def test_oom(self, test_file):
with pytest.raises(UnidentifiedImageError):
with Image.open(test_file) as im:
im.load()
@pytest.mark.skipif(not is_win32(), reason="Windows only")
class TestFileTiffW32:

View File

@ -257,6 +257,8 @@ OPEN_INFO = {
(MM, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"),
}
MAX_SAMPLESPERPIXEL = max(len(key_tp[4]) for key_tp in OPEN_INFO.keys())
PREFIXES = [
b"MM\x00\x2A", # Valid TIFF header with big-endian byte order
b"II\x2A\x00", # Valid TIFF header with little-endian byte order
@ -1396,6 +1398,12 @@ class TiffImageFile(ImageFile.ImageFile):
SAMPLESPERPIXEL,
3 if self._compression == "tiff_jpeg" and photo in (2, 6) else 1,
)
if samples_per_pixel > MAX_SAMPLESPERPIXEL:
# DOS check, samples_per_pixel can be a Long, and we extend the tuple below
logger.error("More samples per pixel than can be decoded: %s", samples_per_pixel)
raise SyntaxError("Invalid value for samples per pixel")
if samples_per_pixel < bps_actual_count:
# If a file has more values in bps_tuple than expected,
# remove the excess.