Skip to content

Commit

Permalink
Merge pull request #4101 from radarhere/negative_seek
Browse files Browse the repository at this point in the history
Corrected negative seeks
  • Loading branch information
radarhere authored Sep 30, 2019
2 parents 152ed62 + 87c43b6 commit b36c1bc
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 4 deletions.
Binary file added Tests/images/combined_larger_than_size.psd
Binary file not shown.
Binary file added Tests/images/raw_negative_stride.bin
Binary file not shown.
9 changes: 9 additions & 0 deletions Tests/test_file_psd.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,12 @@ 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")
8 changes: 8 additions & 0 deletions Tests/test_imagefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,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")
Expand Down
6 changes: 4 additions & 2 deletions src/PIL/PsdImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,11 @@ def _layerinfo(file):
# skip over blend flags and extra information
read(12) # filler
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:
file.seek(length - 16, io.SEEK_CUR)
Expand All @@ -244,7 +246,7 @@ def _layerinfo(file):
name = read(length).decode("latin-1", "replace")
combined += length + 1

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

# get tiles
Expand Down
11 changes: 9 additions & 2 deletions src/libImaging/RawDecode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit b36c1bc

Please sign in to comment.