Should not raise an exception during parsing of XML box. #184

This commit is contained in:
John Evans 2014-03-12 20:50:42 -04:00
commit 42e1b21356
3 changed files with 27 additions and 7 deletions

View file

@ -2631,19 +2631,22 @@ class XMLBox(Jp2kBox):
read_buffer = fptr.read(num_bytes)
try:
text = read_buffer.decode('utf-8')
except UnicodeDecodeError as ude:
except UnicodeDecodeError as err:
# Possibly bad string of bytes to begin with.
# Try to search for <?xml and go from there.
decl_start = read_buffer.find(b'<?xml')
if decl_start > -1:
text = read_buffer[decl_start:].decode('utf-8')
else:
raise
if decl_start <= -1:
msg = 'A problem was encountered while parsing an XML box:'
msg += '\n\n\t"{0}"\n\nNo XML was retrieved.'
warnings.warn(msg.format(str(err)))
return XMLBox(xml=None, length=length, offset=offset)
text = read_buffer[decl_start:].decode('utf-8')
# Let the user know that the XML box was problematic.
msg = 'A UnicodeDecodeError was encountered parsing an XML box at '
msg += 'byte position {0} ({1}), but the XML was still recovered.'
msg = msg.format(offset, ude.reason)
msg = msg.format(offset, err.reason)
warnings.warn(msg, UserWarning)
# Strip out any trailing nulls, as they can foul up XML parsing.

View file

@ -40,7 +40,7 @@ class TestCodestream(unittest.TestCase):
Jp2k(filename)
else:
with self.assertWarns(UserWarning):
Jp2k(jfile)
Jp2k(filename)
@unittest.skipIf(OPJ_DATA_ROOT is None,

View file

@ -39,6 +39,7 @@ from glymur.jp2box import ColourSpecificationBox, ContiguousCodestreamBox
from glymur.jp2box import FileTypeBox, ImageHeaderBox, JP2HeaderBox
from glymur.jp2box import JPEG2000SignatureBox
from .fixtures import OPJ_DATA_ROOT, opj_data_file
@unittest.skipIf(os.name == "nt", "Temporary file issue on window.")
class TestXML(unittest.TestCase):
@ -93,6 +94,22 @@ class TestXML(unittest.TestCase):
def tearDown(self):
os.unlink(self.xmlfile)
def test_invalid_utf8(self):
"""Bad byte sequence that cannot be parsed."""
filename = opj_data_file(os.path.join('input',
'nonregression',
'26ccf3651020967f7778238ef5af08af.SIGFPE.d25.527.jp2'))
if sys.hexversion < 0x03000000:
with warnings.catch_warnings():
warnings.simplefilter("ignore")
jp2 = Jp2k(filename)
else:
with self.assertWarns(UserWarning):
jp2 = Jp2k(filename)
self.assertIsNone(jp2.box[3].box[1].box[1].xml)
def test_negative_file_and_xml(self):
"""The XML should come from only one source."""
xml_object = ET.parse(self.xmlfile)