Skip to content

Commit

Permalink
Merge pull request #20 from ActiveState/BE-2346-cve-2022-45199
Browse files Browse the repository at this point in the history
  • Loading branch information
icanhasmath committed Apr 24, 2023
2 parents fefc469 + 734edca commit 1b07df1
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 8 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Expand Up @@ -27,6 +27,9 @@ Changelog (Pillow)
combination of \r and \n as line endings.
[rickprice]

- Fix CVE-2022-45199: Pillow before 9.3.0 allows denial of service via SAMPLESPERPIXEL.
[rickprice]

- Fix CVE-2021-28676: FliDecode did not properly check that the block advance
was non-zero, potentally leading to an infinite loop on load.
[rickprice]
Expand Down
Binary file not shown.
20 changes: 16 additions & 4 deletions Tests/test_file_tiff.py
Expand Up @@ -2,7 +2,9 @@
import sys
from io import BytesIO

from PIL import Image, TiffImagePlugin
import pytest

from PIL import Image, ImageFile, TiffImagePlugin, UnidentifiedImageError
from PIL._util import py3
from PIL.TiffImagePlugin import RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION

Expand All @@ -13,7 +15,6 @@

class TestFileTiff(PillowTestCase):
def test_sanity(self):

filename = self.tempfile("temp.tif")

hopper("RGB").save(filename)
Expand Down Expand Up @@ -223,8 +224,8 @@ def test_16bit_s(self):
self.assertEqual(im.getpixel((0, 1)), 0)

def test_12bit_rawmode(self):
""" Are we generating the same interpretation
of the image as Imagemagick is? """
"""Are we generating the same interpretation
of the image as Imagemagick is?"""

im = Image.open("Tests/images/12bit.cropped.tif")

Expand Down Expand Up @@ -616,6 +617,17 @@ def test_fd_leak(self):
tmpfile = self.tempfile("temp.tif")
import os

@pytest.mark.parametrize(
"test_file",
[
"Tests/images/oom-225817ca0f8c663be7ab4b9e717b02c661e66834.tif",
],
)
def test_oom(self, test_file):
with pytest.raises(UnidentifiedImageError):
with Image.open(test_file) as im:
pass

# this is an mmaped file.
with Image.open("Tests/images/uint16_1_4660.tif") as im:
im.save(tmpfile)
Expand Down
2 changes: 2 additions & 0 deletions docs/releasenotes/6.2.2.5.rst
Expand Up @@ -37,3 +37,5 @@ This release addresses several critical CVEs.
Pillow in the open phase, before an image was accepted
for opening.

:cve: `CVE-2022-45199`: Pillow before 9.3.0 allows denial of service via SAMPLESPERPIXEL.

25 changes: 21 additions & 4 deletions src/PIL/TiffImagePlugin.py
Expand Up @@ -261,6 +261,8 @@
(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
Expand Down Expand Up @@ -1264,10 +1266,25 @@ def _setup(self):
else:
bps_count = 1
bps_count += len(extra_tuple)
# Some files have only one value in bps_tuple,
# while should have more. Fix it
if bps_count > len(bps_tuple) and len(bps_tuple) == 1:
bps_tuple = bps_tuple * bps_count
bps_actual_count = len(bps_tuple)
samples_per_pixel = self.tag_v2.get(
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.
bps_tuple = bps_tuple[:samples_per_pixel]
elif samples_per_pixel > bps_actual_count and bps_actual_count == 1:
# If a file has only one value in bps_tuple, when it should have more,
# presume it is the same number of bits for all of the samples.
bps_tuple = bps_tuple * samples_per_pixel

# mode: check photometric interpretation and bits per pixel
key = (
Expand Down

0 comments on commit 1b07df1

Please sign in to comment.