File 001-Corrected-negative-seeks.patch of Package python-Pillow
From 87c43b66a5ffe0d21e04dce631a5fd4004e6021b Mon Sep 17 00:00:00 2001
From: Andrew Murray <radarhere@users.noreply.github.com>
Date: Sun, 29 Sep 2019 14:16:30 +1000
Subject: [PATCH] Corrected negative seeks
---
Tests/test_file_psd.py | 9 +++++++++
Tests/test_imagefile.py | 8 ++++++++
src/PIL/PsdImagePlugin.py | 6 ++++--
src/libImaging/RawDecode.c | 11 +++++++++--
4 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/Tests/test_file_psd.py b/Tests/test_file_psd.py
index f55ee1dcbb..8381ceaefc 100644
--- a/Tests/test_file_psd.py
+++ b/Tests/test_file_psd.py
@@ -79,6 +79,15 @@ def test_no_icc_profile(self):
im = Image.open("Tests/images/hopper_merged.psd")
self.assertNotIn("icc_profile", im.info)
+
+ def test_combined_larger_than_size(self):
+ # The 'combined' sizes of the individual parts is larger than the
+ # declared 'size' of the extra data field, resulting in a backwards seek.
+
+ # If we instead take the 'size' of the extra data field as the source of truth,
+ # then the seek can't be negative
+ with self.assertRaises(IOError):
+ Image.open("Tests/images/combined_larger_than_size.psd")
if __name__ == '__main__':
diff --git a/Tests/test_imagefile.py b/Tests/test_imagefile.py
index ceccd22855..a367f62dfa 100644
--- a/Tests/test_imagefile.py
+++ b/Tests/test_imagefile.py
@@ -100,6 +100,14 @@ def test_raise_typeerror(self):
parser = ImageFile.Parser()
parser.feed(1)
+ def test_negative_stride(self):
+ with open("Tests/images/raw_negative_stride.bin", "rb") as f:
+ input = f.read()
+ p = ImageFile.Parser()
+ p.feed(input)
+ with self.assertRaises(IOError):
+ p.close()
+
def test_truncated_with_errors(self):
if "zip_encoder" not in codecs:
self.skipTest("PNG (zlib) encoder not available")
diff --git a/PIL/PsdImagePlugin.py b/PIL/PsdImagePlugin.py
index 9eb0c09669..f72ad5f443 100644
--- a/PIL/PsdImagePlugin.py
+++ b/PIL/PsdImagePlugin.py
@@ -209,9 +209,11 @@ def _layerinfo(file):
# skip over blend flags and extra information
filler = read(12)
name = ""
- size = i32(read(4))
+ size = i32(read(4)) # length of the extra data field
combined = 0
if size:
+ data_end = file.tell() + size
+
length = i32(read(4))
if length:
mask_y = i32(read(4))
@@ -233,7 +235,7 @@ def _layerinfo(file):
name = read(length).decode('latin-1', 'replace')
combined += length + 1
- file.seek(size - combined, 1)
+ file.seek(data_end)
layers.append((name, mode, (x0, y0, x1, y1)))
# get tiles
diff --git a/libImaging/RawDecode.c b/libImaging/RawDecode.c
index 774d4245b8..c069bdb886 100644
--- a/libImaging/RawDecode.c
+++ b/libImaging/RawDecode.c
@@ -33,8 +33,15 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
/* get size of image data and padding */
state->bytes = (state->xsize * state->bits + 7) / 8;
- rawstate->skip = (rawstate->stride) ?
- rawstate->stride - state->bytes : 0;
+ if (rawstate->stride) {
+ rawstate->skip = rawstate->stride - state->bytes;
+ if (rawstate->skip < 0) {
+ state->errcode = IMAGING_CODEC_CONFIG;
+ return -1;
+ }
+ } else {
+ rawstate->skip = 0;
+ }
/* check image orientation */
if (state->ystep < 0) {