mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 01:16:16 +03:00
Merge pull request #3023 from kkopachev/issue-3022
Certain corrupted jpegs can result in no data read
This commit is contained in:
commit
d173e81798
BIN
Tests/images/truncated_jpeg.jpg
Normal file
BIN
Tests/images/truncated_jpeg.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.5 KiB |
|
@ -348,6 +348,22 @@ class TestFileJpeg(PillowTestCase):
|
|||
filename = "Tests/images/jpeg_ff00_header.jpg"
|
||||
Image.open(filename)
|
||||
|
||||
def test_truncated_jpeg_should_read_all_the_data(self):
|
||||
filename = "Tests/images/truncated_jpeg.jpg"
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = True
|
||||
im = Image.open(filename)
|
||||
im.load()
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = False
|
||||
self.assertIsNotNone(im.getbbox())
|
||||
|
||||
def test_truncated_jpeg_throws_IOError(self):
|
||||
filename = "Tests/images/truncated_jpeg.jpg"
|
||||
im = Image.open(filename)
|
||||
|
||||
with self.assertRaises(IOError):
|
||||
im.load()
|
||||
|
||||
|
||||
def _n_qtables_helper(self, n, test_file):
|
||||
im = Image.open(test_file)
|
||||
f = self.tempfile('temp.jpg')
|
||||
|
|
|
@ -202,44 +202,39 @@ class ImageFile(Image.Image):
|
|||
for decoder_name, extents, offset, args in self.tile:
|
||||
decoder = Image._getdecoder(self.mode, decoder_name,
|
||||
args, self.decoderconfig)
|
||||
seek(offset)
|
||||
decoder.setimage(self.im, extents)
|
||||
if decoder.pulls_fd:
|
||||
decoder.setfd(self.fp)
|
||||
status, err_code = decoder.decode(b"")
|
||||
else:
|
||||
b = prefix
|
||||
while True:
|
||||
try:
|
||||
s = read(self.decodermaxblock)
|
||||
except (IndexError, struct.error): # truncated png/gif
|
||||
if LOAD_TRUNCATED_IMAGES:
|
||||
try:
|
||||
seek(offset)
|
||||
decoder.setimage(self.im, extents)
|
||||
if decoder.pulls_fd:
|
||||
decoder.setfd(self.fp)
|
||||
status, err_code = decoder.decode(b"")
|
||||
else:
|
||||
b = prefix
|
||||
while True:
|
||||
try:
|
||||
s = read(self.decodermaxblock)
|
||||
except (IndexError, struct.error): # truncated png/gif
|
||||
if LOAD_TRUNCATED_IMAGES:
|
||||
break
|
||||
else:
|
||||
raise IOError("image file is truncated")
|
||||
|
||||
if not s: # truncated jpeg
|
||||
if LOAD_TRUNCATED_IMAGES:
|
||||
break
|
||||
else:
|
||||
self.tile = []
|
||||
raise IOError("image file is truncated "
|
||||
"(%d bytes not processed)" % len(b))
|
||||
|
||||
b = b + s
|
||||
n, err_code = decoder.decode(b)
|
||||
if n < 0:
|
||||
break
|
||||
else:
|
||||
raise IOError("image file is truncated")
|
||||
|
||||
if not s: # truncated jpeg
|
||||
self.tile = []
|
||||
|
||||
# JpegDecode needs to clean things up here either way
|
||||
# If we don't destroy the decompressor,
|
||||
# we have a memory leak.
|
||||
decoder.cleanup()
|
||||
|
||||
if LOAD_TRUNCATED_IMAGES:
|
||||
break
|
||||
else:
|
||||
raise IOError("image file is truncated "
|
||||
"(%d bytes not processed)" % len(b))
|
||||
|
||||
b = b + s
|
||||
n, err_code = decoder.decode(b)
|
||||
if n < 0:
|
||||
break
|
||||
b = b[n:]
|
||||
|
||||
# Need to cleanup here to prevent leaks in PyPy
|
||||
decoder.cleanup()
|
||||
b = b[n:]
|
||||
finally:
|
||||
# Need to cleanup here to prevent leaks
|
||||
decoder.cleanup()
|
||||
|
||||
self.tile = []
|
||||
self.readonly = readonly
|
||||
|
|
|
@ -353,6 +353,21 @@ class JpegImageFile(ImageFile.ImageFile):
|
|||
else:
|
||||
raise SyntaxError("no marker found")
|
||||
|
||||
def load_read(self, read_bytes):
|
||||
"""
|
||||
internal: read more image data
|
||||
For premature EOF and LOAD_TRUNCATED_IMAGES adds EOI marker
|
||||
so libjpeg can finish decoding
|
||||
"""
|
||||
s = self.fp.read(read_bytes)
|
||||
|
||||
if not s and ImageFile.LOAD_TRUNCATED_IMAGES:
|
||||
# Premature EOF.
|
||||
# Pretend file is finished adding EOI marker
|
||||
return b"\xFF\xD9"
|
||||
|
||||
return s
|
||||
|
||||
def draft(self, mode, size):
|
||||
|
||||
if len(self.tile) != 1:
|
||||
|
|
Loading…
Reference in New Issue
Block a user