diff options
author | David Tardon <dtardon@redhat.com> | 2015-07-20 19:01:20 +0200 |
---|---|---|
committer | David Tardon <dtardon@redhat.com> | 2015-07-20 19:11:45 +0200 |
commit | 781201586a451393c62dde1c43dfb481c8dbaf24 (patch) | |
tree | 1adc878c816fb096ac85ab62301d730d6ca63802 | |
parent | c19e87440ef2d79ba199881c983f2be94fbef907 (diff) |
handle more infinite loops in XML parser
Change-Id: Ia39b230bd9ec76ba9bfa49820ea64f72ca1f35a6
-rw-r--r-- | src/lib/VSDXParser.cpp | 96 | ||||
-rw-r--r-- | src/lib/VSDXParser.h | 2 |
2 files changed, 57 insertions, 41 deletions
diff --git a/src/lib/VSDXParser.cpp b/src/lib/VSDXParser.cpp index e5cee1e..33f5695 100644 --- a/src/lib/VSDXParser.cpp +++ b/src/lib/VSDXParser.cpp @@ -302,55 +302,69 @@ void libvisio::VSDXParser::processXmlDocument(librevenge::RVNGInputStream *input XMLErrorWatcher watcher; const boost::shared_ptr<xmlTextReader> reader( - xmlReaderForStream(input, 0, 0, XML_PARSE_NOBLANKS|XML_PARSE_NOENT|XML_PARSE_NONET, &watcher), - xmlFreeTextReader); + xmlReaderForStream(input, 0, 0, XML_PARSE_NOBLANKS|XML_PARSE_NOENT|XML_PARSE_NONET, &watcher), + xmlFreeTextReader); if (!reader) return; - int ret = xmlTextReaderRead(reader.get()); - while (1 == ret && !watcher.isError()) + + XMLErrorWatcher *oldWatcher = m_watcher; + try { - int tokenId = VSDXMLTokenMap::getTokenId(xmlTextReaderConstName(reader.get())); - int tokenType = xmlTextReaderNodeType(reader.get()); + m_watcher = &watcher; - switch (tokenId) + int ret = xmlTextReaderRead(reader.get()); + while (1 == ret && !watcher.isError()) { - case XML_REL: - if (XML_READER_TYPE_ELEMENT == tokenType) + int tokenId = VSDXMLTokenMap::getTokenId(xmlTextReaderConstName(reader.get())); + int tokenType = xmlTextReaderNodeType(reader.get()); + + switch (tokenId) { - boost::shared_ptr<xmlChar> id(xmlTextReaderGetAttribute(reader.get(), BAD_CAST("r:id")), xmlFree); - if (id) + case XML_REL: + if (XML_READER_TYPE_ELEMENT == tokenType) { - const VSDXRelationship *rel = rels.getRelationshipById((char *)id.get()); - if (rel) + boost::shared_ptr<xmlChar> id(xmlTextReaderGetAttribute(reader.get(), BAD_CAST("r:id")), xmlFree); + if (id) { - std::string type = rel->getType(); - if (type == "http://schemas.microsoft.com/visio/2010/relationships/master") - { - m_currentDepth += xmlTextReaderDepth(reader.get()); - parseMaster(m_input, rel->getTarget().c_str()); - m_currentDepth -= xmlTextReaderDepth(reader.get()); - } - else if (type == "http://schemas.microsoft.com/visio/2010/relationships/page") - { - m_currentDepth += xmlTextReaderDepth(reader.get()); - parsePage(m_input, rel->getTarget().c_str()); - m_currentDepth -= xmlTextReaderDepth(reader.get()); - } - else if (type == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") + const VSDXRelationship *rel = rels.getRelationshipById((char *)id.get()); + if (rel) { - extractBinaryData(m_input, rel->getTarget().c_str()); + std::string type = rel->getType(); + if (type == "http://schemas.microsoft.com/visio/2010/relationships/master") + { + m_currentDepth += xmlTextReaderDepth(reader.get()); + parseMaster(m_input, rel->getTarget().c_str()); + m_currentDepth -= xmlTextReaderDepth(reader.get()); + } + else if (type == "http://schemas.microsoft.com/visio/2010/relationships/page") + { + m_currentDepth += xmlTextReaderDepth(reader.get()); + parsePage(m_input, rel->getTarget().c_str()); + m_currentDepth -= xmlTextReaderDepth(reader.get()); + } + else if (type == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") + { + extractBinaryData(m_input, rel->getTarget().c_str()); + } + else + processXmlNode(reader.get()); } - else - processXmlNode(reader.get()); } } + break; + default: + processXmlNode(reader.get()); + break; } - break; - default: - processXmlNode(reader.get()); - break; + ret = xmlTextReaderRead(reader.get()); } - ret = xmlTextReaderRead(reader.get()); + + m_watcher = oldWatcher; + } + catch (...) + { + m_watcher = oldWatcher; + throw; } } @@ -639,7 +653,7 @@ void libvisio::VSDXParser::readPageSheetProperties(xmlTextReaderPtr reader) break; } } - while ((XML_PAGESHEET != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); + while ((XML_PAGESHEET != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret && !m_watcher->isError()); if (m_isStencilStarted && m_currentStencil) { @@ -682,7 +696,7 @@ void libvisio::VSDXParser::readFonts(xmlTextReaderPtr reader) ++idx; } } - while ((XML_FACENAMES != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); + while ((XML_FACENAMES != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret && !m_watcher->isError()); } void libvisio::VSDXParser::readStyleProperties(xmlTextReaderPtr reader) @@ -874,7 +888,7 @@ void libvisio::VSDXParser::readStyleProperties(xmlTextReaderPtr reader) break; } } - while ((XML_STYLESHEET != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); + while ((XML_STYLESHEET != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret && !m_watcher->isError()); #if 0 if (bgClrId < 0) @@ -1255,7 +1269,7 @@ void libvisio::VSDXParser::readShapeProperties(xmlTextReaderPtr reader) break; } } - while ((XML_SHAPES != tokenId) && (XML_SHAPE != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); + while ((XML_SHAPES != tokenId) && (XML_SHAPE != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret && !m_watcher->isError()); if (1 == ret) processXmlNode(reader); @@ -1279,7 +1293,7 @@ void libvisio::VSDXParser::readParagraph(xmlTextReaderPtr reader) if (XML_ROW == tokenId && XML_READER_TYPE_ELEMENT == tokenType) readParaIX(reader); } - while ((XML_SECTION != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); + while ((XML_SECTION != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret && !m_watcher->isError()); } void libvisio::VSDXParser::readCharacter(xmlTextReaderPtr reader) @@ -1300,7 +1314,7 @@ void libvisio::VSDXParser::readCharacter(xmlTextReaderPtr reader) if (XML_ROW == tokenId && XML_READER_TYPE_ELEMENT == tokenType) readCharIX(reader); } - while ((XML_SECTION != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret); + while ((XML_SECTION != tokenId || XML_READER_TYPE_END_ELEMENT != tokenType) && 1 == ret && !m_watcher->isError()); } void libvisio::VSDXParser::getBinaryData(xmlTextReaderPtr reader) diff --git a/src/lib/VSDXParser.h b/src/lib/VSDXParser.h index 9eef41e..419e53a 100644 --- a/src/lib/VSDXParser.h +++ b/src/lib/VSDXParser.h @@ -18,6 +18,7 @@ namespace libvisio { class VSDCollector; +class XMLErrorWatcher; class VSDXParser : public VSDXMLParserBase { @@ -81,6 +82,7 @@ private: int m_currentDepth; VSDXRelationships *m_rels; VSDXTheme m_currentTheme; + XMLErrorWatcher *m_watcher; }; } // namespace libvisio |