Skip to content

Commit

Permalink
Merge pull request #5174 from radarhere/pcx
Browse files Browse the repository at this point in the history
Fix for Read Overflow in PCX Decoding
  • Loading branch information
radarhere committed Jan 2, 2021
2 parents 120eea2 + 903c673 commit 0117694
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 14 deletions.
Binary file added Tests/images/ossfuzz-4836216264589312.pcx
Binary file not shown.
32 changes: 20 additions & 12 deletions Tests/test_image.py
Expand Up @@ -775,26 +775,34 @@ def test_pillow_version(self, test_module):
with pytest.warns(DeprecationWarning):
assert test_module.PILLOW_VERSION > "7.0.0"

def test_overrun(self):
"""For overrun completeness, test as:
valgrind pytest -qq Tests/test_image.py::TestImage::test_overrun | grep decode.c
"""
for file in [
@pytest.mark.parametrize(
"path",
[
"fli_overrun.bin",
"sgi_overrun.bin",
"sgi_overrun_expandrow.bin",
"sgi_overrun_expandrow2.bin",
"pcx_overrun.bin",
"pcx_overrun2.bin",
"ossfuzz-4836216264589312.pcx",
"01r_00.pcx",
]:
with Image.open(os.path.join("Tests/images", file)) as im:
try:
im.load()
assert False
except OSError as e:
assert str(e) == "buffer overrun when reading image file"
],
)
def test_overrun(self, path):
"""For overrun completeness, test as:
valgrind pytest -qq Tests/test_image.py::TestImage::test_overrun | grep decode.c
"""
with Image.open(os.path.join("Tests/images", path)) as im:
try:
im.load()
assert False
except OSError as e:
buffer_overrun = str(e) == "buffer overrun when reading image file"
truncated = "image file is truncated" in str(e)

assert buffer_overrun or truncated

def test_fli_overrun2(self):
with Image.open("Tests/images/fli_overrun2.bin") as im:
try:
im.seek(1)
Expand Down
9 changes: 7 additions & 2 deletions src/PIL/PcxImagePlugin.py
Expand Up @@ -66,13 +66,13 @@ def _open(self):
version = s[1]
bits = s[3]
planes = s[65]
stride = i16(s, 66)
ignored_stride = i16(s, 66)
logger.debug(
"PCX version %s, bits %s, planes %s, stride %s",
version,
bits,
planes,
stride,
ignored_stride,
)

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

# don't trust the passed in stride. Calculate for ourselves.
# CVE-2020-35655
stride = (self._size[0] * bits + 7) // 8
stride += stride % 2

bbox = (0, 0) + self.size
logger.debug("size: %sx%s", *self.size)

Expand Down

0 comments on commit 0117694

Please sign in to comment.