From ad3e7ccee8b1c18c982c39248625d5230cd3d283 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Sun, 8 Jul 2018 21:35:45 +0200 Subject: [PATCH] Bump coverage for office files and fix some related crashes --- libmat2/office.py | 26 ++++++++++++++------------ tests/data/embedded_corrupted.docx | Bin 0 -> 223581 bytes tests/data/embedded_corrupted.odt | Bin 0 -> 217315 bytes tests/test_corrupted_files.py | 15 +++++++++++++++ 4 files changed, 29 insertions(+), 12 deletions(-) create mode 100644 tests/data/embedded_corrupted.docx create mode 100644 tests/data/embedded_corrupted.odt diff --git a/libmat2/office.py b/libmat2/office.py index 5165056..6087c47 100644 --- a/libmat2/office.py +++ b/libmat2/office.py @@ -147,7 +147,10 @@ class MSOfficeParser(ArchiveBasedAbstractParser): """ In this function, we're changing the XML document in two times, since we don't want to change the tree we're iterating on.""" - tree, ns = _parse_xml(full_path) + try: + tree, ns = _parse_xml(full_path) + except ET.ParseError: + return False # No revisions are present del_presence = tree.find('.//w:del', ns) @@ -191,15 +194,13 @@ class MSOfficeParser(ArchiveBasedAbstractParser): zipin = zipfile.ZipFile(self.filename) for item in zipin.infolist(): if item.filename.startswith('docProps/') and item.filename.endswith('.xml'): - content = zipin.read(item).decode('utf-8') try: + content = zipin.read(item).decode('utf-8') results = re.findall(r"<(.+)>(.+)", content, re.I|re.M) for (key, value) in results: metadata[key] = value - except TypeError: # We didn't manage to parse the xml file - pass - if not metadata: # better safe than sorry - metadata[item] = 'harmful content' + except (TypeError, UnicodeDecodeError): # We didn't manage to parse the xml file + metadata[item.filename] = 'harmful content' for key, value in self._get_zipinfo_meta(item).items(): metadata[key] = value zipin.close() @@ -232,7 +233,10 @@ class LibreOfficeParser(ArchiveBasedAbstractParser): def __remove_revisions(self, full_path: str) -> bool: - tree, ns = _parse_xml(full_path) + try: + tree, ns = _parse_xml(full_path) + except ET.ParseError: + return False if 'office' not in ns.keys(): # no revisions in the current file return True @@ -259,15 +263,13 @@ class LibreOfficeParser(ArchiveBasedAbstractParser): zipin = zipfile.ZipFile(self.filename) for item in zipin.infolist(): if item.filename == 'meta.xml': - content = zipin.read(item).decode('utf-8') try: + content = zipin.read(item).decode('utf-8') results = re.findall(r"<((?:meta|dc|cp).+?)>(.+)", content, re.I|re.M) for (key, value) in results: metadata[key] = value - except TypeError: # We didn't manage to parse the xml file - pass - if not metadata: # better safe than sorry - metadata[item] = 'harmful content' + except (TypeError, UnicodeDecodeError): # We didn't manage to parse the xml file + metadata[item.filename] = 'harmful content' for key, value in self._get_zipinfo_meta(item).items(): metadata[key] = value zipin.close() diff --git a/tests/data/embedded_corrupted.docx b/tests/data/embedded_corrupted.docx new file mode 100644 index 0000000000000000000000000000000000000000..989bdb8e96e1962c48cecc83311e5fd1aad76655 GIT binary patch literal 223581 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