Skip to content

Commit 87c43b6

Browse files
committed
Corrected negative seeks
1 parent 152ed62 commit 87c43b6

File tree

6 files changed

+30
-4
lines changed

6 files changed

+30
-4
lines changed
285 Bytes
Binary file not shown.

Tests/images/raw_negative_stride.bin

2.4 KB
Binary file not shown.

Tests/test_file_psd.py

+9
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,12 @@ def test_no_icc_profile(self):
8787
im = Image.open("Tests/images/hopper_merged.psd")
8888

8989
self.assertNotIn("icc_profile", im.info)
90+
91+
def test_combined_larger_than_size(self):
92+
# The 'combined' sizes of the individual parts is larger than the
93+
# declared 'size' of the extra data field, resulting in a backwards seek.
94+
95+
# If we instead take the 'size' of the extra data field as the source of truth,
96+
# then the seek can't be negative
97+
with self.assertRaises(IOError):
98+
Image.open("Tests/images/combined_larger_than_size.psd")

Tests/test_imagefile.py

+8
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ def test_raise_typeerror(self):
103103
parser = ImageFile.Parser()
104104
parser.feed(1)
105105

106+
def test_negative_stride(self):
107+
with open("Tests/images/raw_negative_stride.bin", "rb") as f:
108+
input = f.read()
109+
p = ImageFile.Parser()
110+
p.feed(input)
111+
with self.assertRaises(IOError):
112+
p.close()
113+
106114
def test_truncated_with_errors(self):
107115
if "zip_encoder" not in codecs:
108116
self.skipTest("PNG (zlib) encoder not available")

src/PIL/PsdImagePlugin.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,11 @@ def _layerinfo(file):
224224
# skip over blend flags and extra information
225225
read(12) # filler
226226
name = ""
227-
size = i32(read(4))
227+
size = i32(read(4)) # length of the extra data field
228228
combined = 0
229229
if size:
230+
data_end = file.tell() + size
231+
230232
length = i32(read(4))
231233
if length:
232234
file.seek(length - 16, io.SEEK_CUR)
@@ -244,7 +246,7 @@ def _layerinfo(file):
244246
name = read(length).decode("latin-1", "replace")
245247
combined += length + 1
246248

247-
file.seek(size - combined, io.SEEK_CUR)
249+
file.seek(data_end)
248250
layers.append((name, mode, (x0, y0, x1, y1)))
249251

250252
# get tiles

src/libImaging/RawDecode.c

+9-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,15 @@ ImagingRawDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
3333

3434
/* get size of image data and padding */
3535
state->bytes = (state->xsize * state->bits + 7) / 8;
36-
rawstate->skip = (rawstate->stride) ?
37-
rawstate->stride - state->bytes : 0;
36+
if (rawstate->stride) {
37+
rawstate->skip = rawstate->stride - state->bytes;
38+
if (rawstate->skip < 0) {
39+
state->errcode = IMAGING_CODEC_CONFIG;
40+
return -1;
41+
}
42+
} else {
43+
rawstate->skip = 0;
44+
}
3845

3946
/* check image orientation */
4047
if (state->ystep < 0) {

0 commit comments

Comments
 (0)