From 5f9fff02155957287154787a9d1d235845108cea Mon Sep 17 00:00:00 2001 From: wiredfool Date: Fri, 11 Sep 2015 10:45:10 -0700 Subject: [PATCH] Restoring bad exif handling --- PIL/TiffImagePlugin.py | 90 +++++++++++++++++++++++------------------ Tests/test_file_tiff.py | 8 ++-- 2 files changed, 56 insertions(+), 42 deletions(-) diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index de2381b34..4638acd8f 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -468,55 +468,67 @@ class ImageFileDirectory_v2(collections.MutableMapping): return b"".join(self._pack("2L", *_limit_rational(frac, 2 ** 30)) for frac in values) + def _ensure_read(self, fp, size): + ret = fp.read(size) + if len(ret) != size: + raise IOError("Corrupt EXIF data. " + + "Expecting to read %d bytes but only got %d. " % + (size, len(ret))) + return ret + def load(self, fp): self.reset() self._offset = fp.tell() - for i in range(self._unpack("H", fp.read(2))[0]): - tag, typ, count, data = self._unpack("HHL4s", fp.read(12)) - if DEBUG: - tagname = TAGS.get(tag, TagInfo()).name - typname = TYPES.get(typ, "unknown") - print("tag: %s (%d) - type: %s (%d)" % - (tagname, tag, typname, typ), end=" ") - - try: - unit_size, handler = self._load_dispatch[typ] - except KeyError: + try: + for i in range(self._unpack("H", self._ensure_read(fp,2))[0]): + tag, typ, count, data = self._unpack("HHL4s", self._ensure_read(fp,12)) if DEBUG: - print("- unsupported type", typ) - continue # ignore unsupported type - size = count * unit_size - if size > 4: - here = fp.tell() - offset, = self._unpack("L", data) - if DEBUG: - print("Tag Location: %s - Data Location: %s" % - (here, offset), end=" ") - fp.seek(offset) - data = ImageFile._safe_read(fp, size) - fp.seek(here) - else: - data = data[:size] + tagname = TAGS.get(tag, TagInfo()).name + typname = TYPES.get(typ, "unknown") + print("tag: %s (%d) - type: %s (%d)" % + (tagname, tag, typname, typ), end=" ") - if len(data) != size: - warnings.warn("Possibly corrupt EXIF data. " - "Expecting to read %d bytes but only got %d. " - "Skipping tag %s" % (size, len(data), tag)) - continue - - self._tagdata[tag] = data - self.tagtype[tag] = typ - - if DEBUG: - if size > 32: - print("- value: " % size) + try: + unit_size, handler = self._load_dispatch[typ] + except KeyError: + if DEBUG: + print("- unsupported type", typ) + continue # ignore unsupported type + size = count * unit_size + if size > 4: + here = fp.tell() + offset, = self._unpack("L", data) + if DEBUG: + print("Tag Location: %s - Data Location: %s" % + (here, offset), end=" ") + fp.seek(offset) + data = ImageFile._safe_read(fp, size) + fp.seek(here) else: - print("- value:", self[tag]) + data = data[:size] - self.next, = self._unpack("L", fp.read(4)) + if len(data) != size: + warnings.warn("Possibly corrupt EXIF data. " + "Expecting to read %d bytes but only got %d. " + "Skipping tag %s" % (size, len(data), tag)) + continue + self._tagdata[tag] = data + self.tagtype[tag] = typ + + if DEBUG: + if size > 32: + print("- value: " % size) + else: + print("- value:", self[tag]) + + self.next, = self._unpack("L", self._ensure_read(fp,4)) + except IOError as msg: + warnings.warn(str(msg)) + return + def save(self, fp): if fp.tell() == 0: # skip TIFF header on subsequent pages diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index f5df2c301..7ec6d9e60 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -99,9 +99,11 @@ class TestFileTiff(PillowTestCase): lambda: TiffImagePlugin.TiffImageFile(invalid_file)) def test_bad_exif(self): - image = Image.open('Tests/images/hopper_bad_exif.jpg') - image._getexif() - self.assertRaises(Exception, image._getexif) + try: + Image.open('Tests/images/hopper_bad_exif.jpg')._getexif() + except struct.error: + self.fail( + "Bad EXIF data passed incorrect values to _binary unpack") def test_save_unsupported_mode(self): im = hopper("HSV")