diff --git a/Tests/images/exif-ifd-offset.jpg b/Tests/images/exif-ifd-offset.jpg new file mode 100644 index 000000000..e5dfc6807 Binary files /dev/null and b/Tests/images/exif-ifd-offset.jpg differ diff --git a/Tests/images/sugarshack_ifd_offset.mpo b/Tests/images/sugarshack_ifd_offset.mpo new file mode 100644 index 000000000..2dcac876f Binary files /dev/null and b/Tests/images/sugarshack_ifd_offset.mpo differ diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index 82e55b301..340ae0004 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -581,6 +581,15 @@ class TestFileJpeg(PillowTestCase): # OSError for unidentified image. self.assertEqual(im.info.get("dpi"), (72, 72)) + def test_ifd_offset_exif(self): + # Arrange + # This image has been manually hexedited to have an IFD offset of 10, + # in contrast to normal 8 + im = Image.open("Tests/images/exif-ifd-offset.jpg") + + # Act / Assert + self.assertEqual(im._getexif()[306], '2017:03:13 23:03:09') + @unittest.skipUnless(sys.platform.startswith('win32'), "Windows only") class TestFileCloseW32(PillowTestCase): diff --git a/Tests/test_file_mpo.py b/Tests/test_file_mpo.py index 6f99198c0..bbb9b164d 100644 --- a/Tests/test_file_mpo.py +++ b/Tests/test_file_mpo.py @@ -62,6 +62,14 @@ class TestFileMpo(PillowTestCase): self.assertEqual(mpinfo[45056], b'0100') self.assertEqual(mpinfo[45057], 2) + def test_mp_offset(self): + # This image has been manually hexedited to have an IFD offset of 10 + # in APP2 data, in contrast to normal 8 + im = Image.open("Tests/images/sugarshack_ifd_offset.mpo") + mpinfo = im._getmp() + self.assertEqual(mpinfo[45056], b'0100') + self.assertEqual(mpinfo[45057], 2) + def test_mp_attribute(self): for test_file in test_files: im = Image.open(test_file) diff --git a/src/PIL/JpegImagePlugin.py b/src/PIL/JpegImagePlugin.py index 2616caa57..2f76e9675 100644 --- a/src/PIL/JpegImagePlugin.py +++ b/src/PIL/JpegImagePlugin.py @@ -461,35 +461,36 @@ def _getexif(self): data = self.info["exif"] except KeyError: return None - file = io.BytesIO(data[6:]) - head = file.read(8) + fp = io.BytesIO(data[6:]) + head = fp.read(8) # process dictionary info = TiffImagePlugin.ImageFileDirectory_v1(head) - info.load(file) + fp.seek(info.next) + info.load(fp) exif = dict(_fixup_dict(info)) # get exif extension try: # exif field 0x8769 is an offset pointer to the location # of the nested embedded exif ifd. # It should be a long, but may be corrupted. - file.seek(exif[0x8769]) + fp.seek(exif[0x8769]) except (KeyError, TypeError): pass else: info = TiffImagePlugin.ImageFileDirectory_v1(head) - info.load(file) + info.load(fp) exif.update(_fixup_dict(info)) # get gpsinfo extension try: # exif field 0x8825 is an offset pointer to the location # of the nested embedded gps exif ifd. # It should be a long, but may be corrupted. - file.seek(exif[0x8825]) + fp.seek(exif[0x8825]) except (KeyError, TypeError): pass else: info = TiffImagePlugin.ImageFileDirectory_v1(head) - info.load(file) + info.load(fp) exif[0x8825] = _fixup_dict(info) return exif @@ -512,6 +513,7 @@ def _getmp(self): # process dictionary try: info = TiffImagePlugin.ImageFileDirectory_v2(head) + file_contents.seek(info.next) info.load(file_contents) mp = dict(info) except Exception: