Skip to content

Commit 2f40926

Browse files
wiredfoolradarhere
authored andcommitted
Fix for CVE CVE-2020-35655 - Read Overflow in PCX Decoding.
* Don't trust the image to specify a buffer size
1 parent 0c39689 commit 2f40926

3 files changed

Lines changed: 22 additions & 14 deletions

File tree

129 Bytes
Binary file not shown.

Tests/test_image.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -775,26 +775,29 @@ def test_pillow_version(self, test_module):
775775
with pytest.warns(DeprecationWarning):
776776
assert test_module.PILLOW_VERSION > "7.0.0"
777777

778-
def test_overrun(self):
779-
"""For overrun completeness, test as:
780-
valgrind pytest -qq Tests/test_image.py::TestImage::test_overrun | grep decode.c
781-
"""
782-
for file in [
778+
@pytest.mark.parametrize("path", [
783779
"fli_overrun.bin",
784780
"sgi_overrun.bin",
785781
"sgi_overrun_expandrow.bin",
786782
"sgi_overrun_expandrow2.bin",
787783
"pcx_overrun.bin",
788784
"pcx_overrun2.bin",
785+
"ossfuzz-4836216264589312.pcx",
789786
"01r_00.pcx",
790-
]:
791-
with Image.open(os.path.join("Tests/images", file)) as im:
792-
try:
793-
im.load()
794-
assert False
795-
except OSError as e:
796-
assert str(e) == "buffer overrun when reading image file"
787+
])
788+
def test_overrun(self, path):
789+
"""For overrun completeness, test as:
790+
valgrind pytest -qq Tests/test_image.py::TestImage::test_overrun | grep decode.c
791+
"""
792+
with Image.open(os.path.join("Tests/images", path)) as im:
793+
try:
794+
im.load()
795+
assert False
796+
except OSError as e:
797+
assert (str(e) == "buffer overrun when reading image file" or
798+
"image file is truncated" in str(e))
797799

800+
def test_fli_overrun2(self):
798801
with Image.open("Tests/images/fli_overrun2.bin") as im:
799802
try:
800803
im.seek(1)

src/PIL/PcxImagePlugin.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,13 @@ def _open(self):
6666
version = s[1]
6767
bits = s[3]
6868
planes = s[65]
69-
stride = i16(s, 66)
69+
ignored_stride = i16(s, 66)
7070
logger.debug(
7171
"PCX version %s, bits %s, planes %s, stride %s",
7272
version,
7373
bits,
7474
planes,
75-
stride,
75+
ignored_stride,
7676
)
7777

7878
self.info["dpi"] = i16(s, 12), i16(s, 14)
@@ -110,6 +110,11 @@ def _open(self):
110110
self.mode = mode
111111
self._size = bbox[2] - bbox[0], bbox[3] - bbox[1]
112112

113+
# don't trust the passed in stride. Calculate for ourselves.
114+
# CVE-2020-35655
115+
stride = (self._size[0] * bits + 7) // 8
116+
stride += stride % 2
117+
113118
bbox = (0, 0) + self.size
114119
logger.debug("size: %sx%s", *self.size)
115120

0 commit comments

Comments
 (0)