Skip to content

Commit 2444cdd

Browse files
authored
Merge pull request #6700 from hugovk/security-samples_per_pixel-sec
2 parents e055ef0 + 0846bfa commit 2444cdd

File tree

4 files changed

+35
-1
lines changed

4 files changed

+35
-1
lines changed
Binary file not shown.

Tests/test_file_tiff.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import pytest
66

7-
from PIL import Image, ImageFile, TiffImagePlugin
7+
from PIL import Image, ImageFile, TiffImagePlugin, UnidentifiedImageError
88
from PIL.TiffImagePlugin import RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION
99

1010
from .helper import (
@@ -858,6 +858,19 @@ def test_timeout(self):
858858
im.load()
859859
ImageFile.LOAD_TRUNCATED_IMAGES = False
860860

861+
@pytest.mark.parametrize(
862+
"test_file",
863+
[
864+
"Tests/images/oom-225817ca0f8c663be7ab4b9e717b02c661e66834.tif",
865+
],
866+
)
867+
@pytest.mark.timeout(2)
868+
def test_oom(self, test_file):
869+
with pytest.raises(UnidentifiedImageError):
870+
with pytest.warns(UserWarning):
871+
with Image.open(test_file):
872+
pass
873+
861874

862875
@pytest.mark.skipif(not is_win32(), reason="Windows only")
863876
class TestFileTiffW32:

docs/releasenotes/9.3.0.rst

+11
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ decode the data in its natural CMYK mode, then convert it to RGB and rearrange
4949
the channels afterwards. Trying to load the data in an incorrect mode could
5050
result in a segmentation fault. This issue was introduced in Pillow 9.1.0.
5151

52+
Limit SAMPLESPERPIXEL to avoid runtime DOS
53+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
54+
55+
A large value in the ``SAMPLESPERPIXEL`` tag could lead to a memory and runtime DOS in
56+
``TiffImagePlugin.py`` when setting up the context for image decoding.
57+
This was introduced in Pillow 9.2.0, found with `OSS-Fuzz`_ and fixed by limiting
58+
``SAMPLESPERPIXEL`` to the number of planes that we can decode.
59+
60+
5261
Other Changes
5362
=============
5463

@@ -88,3 +97,5 @@ Show all frames with ImageShow
8897

8998
When calling :py:meth:`~PIL.Image.Image.show` or using
9099
:py:mod:`~PIL.ImageShow`, all frames will now be shown.
100+
101+
.. _OSS-Fuzz: https://github.com/google/oss-fuzz

src/PIL/TiffImagePlugin.py

+10
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@
257257
(MM, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"),
258258
}
259259

260+
MAX_SAMPLESPERPIXEL = max(len(key_tp[4]) for key_tp in OPEN_INFO.keys())
261+
260262
PREFIXES = [
261263
b"MM\x00\x2A", # Valid TIFF header with big-endian byte order
262264
b"II\x2A\x00", # Valid TIFF header with little-endian byte order
@@ -1396,6 +1398,14 @@ def _setup(self):
13961398
SAMPLESPERPIXEL,
13971399
3 if self._compression == "tiff_jpeg" and photo in (2, 6) else 1,
13981400
)
1401+
1402+
if samples_per_pixel > MAX_SAMPLESPERPIXEL:
1403+
# DOS check, samples_per_pixel can be a Long, and we extend the tuple below
1404+
logger.error(
1405+
"More samples per pixel than can be decoded: %s", samples_per_pixel
1406+
)
1407+
raise SyntaxError("Invalid value for samples per pixel")
1408+
13991409
if samples_per_pixel < bps_actual_count:
14001410
# If a file has more values in bps_tuple than expected,
14011411
# remove the excess.

0 commit comments

Comments
 (0)