diff options
author | David Tardon <dtardon@redhat.com> | 2017-04-20 15:53:34 +0200 |
---|---|---|
committer | David Tardon <dtardon@redhat.com> | 2017-04-20 15:53:34 +0200 |
commit | 442b4812cf058481e00c186ef738c990e1a50284 (patch) | |
tree | 4e5ca4176007106e234cc589b3c761c0f1cfeea1 | |
parent | 1fb548389f0bab6767bf0f656d15328bca0e35cf (diff) |
ofz#1025 stop parsing if XML error is encountered
xmlTextReader either does not continue processing the document if it
encounters an error or it can get into an infinite loop in some cases.
XML_PARSE_RECOVER does not help. So we just give up in case of error.
Change-Id: Ib5287a4032b2f9600bd389dcfb2e2cc6babf6ac8
-rw-r--r-- | src/lib/ABWParser.cpp | 7 | ||||
-rw-r--r-- | src/lib/ABWXMLHelper.cpp | 26 | ||||
-rw-r--r-- | src/lib/ABWXMLHelper.h | 17 |
3 files changed, 42 insertions, 8 deletions
diff --git a/src/lib/ABWParser.cpp b/src/lib/ABWParser.cpp index 3f77770..bdbb83d 100644 --- a/src/lib/ABWParser.cpp +++ b/src/lib/ABWParser.cpp @@ -187,11 +187,12 @@ bool libabw::ABWParser::processXmlDocument(librevenge::RVNGInputStream *input) if (!input) return false; - std::shared_ptr<xmlTextReader> reader(xmlReaderForStream(input), xmlFreeTextReader); + ABWXMLErrorWatcher watcher; + std::shared_ptr<xmlTextReader> reader(xmlReaderForStream(input, &watcher), xmlFreeTextReader); if (!reader) return false; int ret = xmlTextReaderRead(reader.get()); - while (1 == ret) + while (1 == ret && !watcher.isError()) { processXmlNode(reader.get()); ret = xmlTextReaderRead(reader.get()); @@ -199,7 +200,7 @@ bool libabw::ABWParser::processXmlDocument(librevenge::RVNGInputStream *input) if (m_collector) m_collector->endDocument(); - return true; + return !watcher.isError(); } void libabw::ABWParser::processXmlNode(xmlTextReaderPtr reader) diff --git a/src/lib/ABWXMLHelper.cpp b/src/lib/ABWXMLHelper.cpp index 553155e..5ce5185 100644 --- a/src/lib/ABWXMLHelper.cpp +++ b/src/lib/ABWXMLHelper.cpp @@ -46,11 +46,12 @@ extern "C" { } #ifdef DEBUG - static void abwxmlReaderErrorFunc(void *, const char *message, xmlParserSeverities severity, xmlTextReaderLocatorPtr) + static void abwxmlReaderErrorFunc(void *arg, const char *message, xmlParserSeverities severity, xmlTextReaderLocatorPtr) #else - static void abwxmlReaderErrorFunc(void *, const char *, xmlParserSeverities severity, xmlTextReaderLocatorPtr) + static void abwxmlReaderErrorFunc(void *arg, const char *, xmlParserSeverities severity, xmlTextReaderLocatorPtr) #endif { + const auto watcher = reinterpret_cast<ABWXMLErrorWatcher *>(arg); switch (severity) { case XML_PARSER_SEVERITY_VALIDITY_WARNING: @@ -64,6 +65,8 @@ extern "C" { break; case XML_PARSER_SEVERITY_ERROR: ABW_DEBUG_MSG(("Found xml parser severity error %s\n", message)); + if (watcher) + watcher->setError(); break; default: break; @@ -89,13 +92,28 @@ ABWXMLString::operator const char *() const return reinterpret_cast<const char *>(m_xml.get()); } +ABWXMLErrorWatcher::ABWXMLErrorWatcher() + : m_error(false) +{ +} + +bool ABWXMLErrorWatcher::isError() const +{ + return m_error; +} + +void ABWXMLErrorWatcher::setError() +{ + m_error = true; +} + // xmlTextReader helper function -xmlTextReaderPtr xmlReaderForStream(librevenge::RVNGInputStream *input) +xmlTextReaderPtr xmlReaderForStream(librevenge::RVNGInputStream *input, ABWXMLErrorWatcher *watcher) { xmlTextReaderPtr reader = xmlReaderForIO(abwxmlInputReadFunc, abwxmlInputCloseFunc, (void *)input, 0, 0, XML_PARSE_NOBLANKS|XML_PARSE_NOENT|XML_PARSE_NONET|XML_PARSE_RECOVER); - xmlTextReaderSetErrorHandler(reader, abwxmlReaderErrorFunc, 0); + xmlTextReaderSetErrorHandler(reader, abwxmlReaderErrorFunc, watcher); return reader; } diff --git a/src/lib/ABWXMLHelper.h b/src/lib/ABWXMLHelper.h index 6008cad..d2b4aea 100644 --- a/src/lib/ABWXMLHelper.h +++ b/src/lib/ABWXMLHelper.h @@ -34,10 +34,25 @@ private: std::shared_ptr<xmlChar> m_xml; }; +class ABWXMLErrorWatcher +{ + ABWXMLErrorWatcher(const ABWXMLErrorWatcher &) = delete; + ABWXMLErrorWatcher &operator=(const ABWXMLErrorWatcher &) = delete; + +public: + ABWXMLErrorWatcher(); + + bool isError() const; + void setError(); + +private: + bool m_error; +}; + // create an xmlTextReader pointer from a librevenge::RVNGInputStream pointer // needs to be freed using xmlTextReaderFree function. -xmlTextReaderPtr xmlReaderForStream(librevenge::RVNGInputStream *input); +xmlTextReaderPtr xmlReaderForStream(librevenge::RVNGInputStream *input, ABWXMLErrorWatcher *watcher = 0); } // namespace libabw |