Made Exif handling more resilient. #104

This commit is contained in:
jevans 2013-10-26 18:05:44 -04:00
commit 7e717b5037
3 changed files with 77 additions and 9 deletions

View file

@ -39,9 +39,13 @@ class UUIDExif(object):
if data[0] == 73 and data[1] == 73: if data[0] == 73 and data[1] == 73:
# little endian # little endian
self.endian = '<' self.endian = '<'
else: elif data[0] == 77 and data[1] == 77:
# big endian # big endian
self.endian = '>' self.endian = '>'
else:
msg = "Bad byte order indication: {0}".format(read_buffer[6:8])
raise RuntimeError(msg)
offset = data[3] offset = data[3]
# This is the 'Exif Image' portion. # This is the 'Exif Image' portion.

View file

@ -19,6 +19,7 @@ import os
import pprint import pprint
import struct import struct
import sys import sys
import traceback
import uuid import uuid
import warnings import warnings
import xml.etree.cElementTree as ET import xml.etree.cElementTree as ET
@ -2078,15 +2079,23 @@ class UUIDBox(Jp2kBox):
Jp2kBox.__init__(self, box_id='uuid', longname='UUID') Jp2kBox.__init__(self, box_id='uuid', longname='UUID')
self.uuid = the_uuid self.uuid = the_uuid
if the_uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'): try:
self.data = _uuid_io.UUIDXMP(raw_data) if the_uuid == uuid.UUID('be7acfcb-97a9-42e8-9c71-999491e3afac'):
self._type = 'XMP' self.data = _uuid_io.UUIDXMP(raw_data)
elif the_uuid.bytes == b'JpgTiffExif->JP2': self._type = 'XMP'
self.data = _uuid_io.UUIDExif(raw_data) elif the_uuid.bytes == b'JpgTiffExif->JP2':
self._type = 'Exif' self.data = _uuid_io.UUIDExif(raw_data)
else: self._type = 'Exif'
else:
self.data = _uuid_io.UUIDGeneric(raw_data)
self._type = 'unknown'
except Exception as err:
# In case of any exception, create the generic UUID.
self.data = _uuid_io.UUIDGeneric(raw_data) self.data = _uuid_io.UUIDGeneric(raw_data)
self._type = 'unknown' self._type = 'unknown'
msg = "Error encountered during UUID processing, "
msg += "the UUID will be treated as generic.\n\n{0}"
warnings.warn(msg.format(traceback.format_exc()))
self.raw_data = raw_data self.raw_data = raw_data

View file

@ -63,7 +63,7 @@ class TestUUIDExif(unittest.TestCase):
xbuffer = struct.pack('<BBHI', 73, 73, 42, 8) xbuffer = struct.pack('<BBHI', 73, 73, 42, 8)
tfile.write(xbuffer) tfile.write(xbuffer)
# We will write just a single file. # We will write just a single tag.
tfile.write(struct.pack('<H', 1)) tfile.write(struct.pack('<H', 1))
# The "Make" tag is tag no. 271. Corrupt it to 171. # The "Make" tag is tag no. 271. Corrupt it to 171.
@ -73,6 +73,61 @@ class TestUUIDExif(unittest.TestCase):
with self.assertWarns(UserWarning): with self.assertWarns(UserWarning):
j = glymur.Jp2k(tfile.name) j = glymur.Jp2k(tfile.name)
@unittest.skipIf(sys.hexversion < 0x03000000, "Requires assertWarns, 3.2+")
def test_bad_tag_datatype(self):
"""Only certain datatypes are allowable"""
with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile:
with open(self.jp2file, 'rb') as ifptr:
tfile.write(ifptr.read())
# Write L, T, UUID identifier.
tfile.write(struct.pack('>I4s', 52, b'uuid'))
tfile.write(b'JpgTiffExif->JP2')
tfile.write(b'Exif\x00\x00')
xbuffer = struct.pack('<BBHI', 73, 73, 42, 8)
tfile.write(xbuffer)
# We will write just a single tag.
tfile.write(struct.pack('<H', 1))
# 2000 is not an allowable TIFF datatype.
tfile.write(struct.pack('<HHI4s', 271, 2000, 3, b'HTC\x00'))
tfile.flush()
with self.assertWarns(UserWarning):
j = glymur.Jp2k(tfile.name)
self.assertEqual(j.box[-1].box_id, 'uuid')
@unittest.skipIf(sys.hexversion < 0x03000000, "Requires assertWarns, 3.2+")
def test_bad_tiff_header_byte_order_indication(self):
"""Only b'II' and b'MM' are allowed."""
with tempfile.NamedTemporaryFile(suffix='.jp2', mode='wb') as tfile:
with open(self.jp2file, 'rb') as ifptr:
tfile.write(ifptr.read())
# Write L, T, UUID identifier.
tfile.write(struct.pack('>I4s', 52, b'uuid'))
tfile.write(b'JpgTiffExif->JP2')
tfile.write(b'Exif\x00\x00')
xbuffer = struct.pack('<BBHI', 74, 73, 42, 8)
tfile.write(xbuffer)
# We will write just a single tag.
tfile.write(struct.pack('<H', 1))
# 271 is the Make.
tfile.write(struct.pack('<HHI4s', 271, 2, 3, b'HTC\x00'))
tfile.flush()
with self.assertWarns(UserWarning):
j = glymur.Jp2k(tfile.name)
self.assertEqual(j.box[-1].box_id, 'uuid')
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()