mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +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"
|
filename = "Tests/images/jpeg_ff00_header.jpg"
|
||||||
Image.open(filename)
|
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):
|
def _n_qtables_helper(self, n, test_file):
|
||||||
im = Image.open(test_file)
|
im = Image.open(test_file)
|
||||||
f = self.tempfile('temp.jpg')
|
f = self.tempfile('temp.jpg')
|
||||||
|
|
|
@ -202,44 +202,39 @@ class ImageFile(Image.Image):
|
||||||
for decoder_name, extents, offset, args in self.tile:
|
for decoder_name, extents, offset, args in self.tile:
|
||||||
decoder = Image._getdecoder(self.mode, decoder_name,
|
decoder = Image._getdecoder(self.mode, decoder_name,
|
||||||
args, self.decoderconfig)
|
args, self.decoderconfig)
|
||||||
seek(offset)
|
try:
|
||||||
decoder.setimage(self.im, extents)
|
seek(offset)
|
||||||
if decoder.pulls_fd:
|
decoder.setimage(self.im, extents)
|
||||||
decoder.setfd(self.fp)
|
if decoder.pulls_fd:
|
||||||
status, err_code = decoder.decode(b"")
|
decoder.setfd(self.fp)
|
||||||
else:
|
status, err_code = decoder.decode(b"")
|
||||||
b = prefix
|
else:
|
||||||
while True:
|
b = prefix
|
||||||
try:
|
while True:
|
||||||
s = read(self.decodermaxblock)
|
try:
|
||||||
except (IndexError, struct.error): # truncated png/gif
|
s = read(self.decodermaxblock)
|
||||||
if LOAD_TRUNCATED_IMAGES:
|
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
|
break
|
||||||
else:
|
b = b[n:]
|
||||||
raise IOError("image file is truncated")
|
finally:
|
||||||
|
# Need to cleanup here to prevent leaks
|
||||||
if not s: # truncated jpeg
|
decoder.cleanup()
|
||||||
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()
|
|
||||||
|
|
||||||
self.tile = []
|
self.tile = []
|
||||||
self.readonly = readonly
|
self.readonly = readonly
|
||||||
|
|
|
@ -353,6 +353,21 @@ class JpegImageFile(ImageFile.ImageFile):
|
||||||
else:
|
else:
|
||||||
raise SyntaxError("no marker found")
|
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):
|
def draft(self, mode, size):
|
||||||
|
|
||||||
if len(self.tile) != 1:
|
if len(self.tile) != 1:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user