From c2031ad6125b4fcd8202778e74b58235cd419f69 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Mon, 20 Jul 2015 18:35:56 +0200 Subject: 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: I29615b656fc9b1dcd39aefbecc67da10c75fe0b6 --- src/lib/VSDXMetaData.cpp | 9 ++++++--- src/lib/libvisio_xml.cpp | 26 ++++++++++++++++++++++---- src/lib/libvisio_xml.h | 19 ++++++++++++++++++- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/lib/VSDXMetaData.cpp b/src/lib/VSDXMetaData.cpp index 3724dc9..2d9a45c 100644 --- a/src/lib/VSDXMetaData.cpp +++ b/src/lib/VSDXMetaData.cpp @@ -117,8 +117,10 @@ bool libvisio::VSDXMetaData::parse(librevenge::RVNGInputStream *input) if (!input) return false; + XMLErrorWatcher watcher; + const boost::shared_ptr reader( - xmlReaderForStream(input, 0, 0, XML_PARSE_NOBLANKS|XML_PARSE_NOENT|XML_PARSE_NONET), + xmlReaderForStream(input, 0, 0, XML_PARSE_NOBLANKS|XML_PARSE_NOENT|XML_PARSE_NONET, &watcher), xmlFreeTextReader); if (!reader) return false; @@ -126,7 +128,7 @@ bool libvisio::VSDXMetaData::parse(librevenge::RVNGInputStream *input) try { int ret = xmlTextReaderRead(reader.get()); - while (1 == ret) + while (1 == ret && !watcher.isError()) { int tokenId = getElementToken(reader.get()); switch (tokenId) @@ -146,7 +148,8 @@ bool libvisio::VSDXMetaData::parse(librevenge::RVNGInputStream *input) { return false; } - return true; + + return !watcher.isError(); } int libvisio::VSDXMetaData::getElementToken(xmlTextReaderPtr reader) diff --git a/src/lib/libvisio_xml.cpp b/src/lib/libvisio_xml.cpp index 09ad165..9941ee9 100644 --- a/src/lib/libvisio_xml.cpp +++ b/src/lib/libvisio_xml.cpp @@ -47,11 +47,12 @@ extern "C" } #ifdef DEBUG - static void vsdxReaderErrorFunc(void *, const char *message, xmlParserSeverities severity, xmlTextReaderLocatorPtr) + static void vsdxReaderErrorFunc(void *arg, const char *message, xmlParserSeverities severity, xmlTextReaderLocatorPtr) #else - static void vsdxReaderErrorFunc(void *, const char *, xmlParserSeverities severity, xmlTextReaderLocatorPtr) + static void vsdxReaderErrorFunc(void *arg, const char *, xmlParserSeverities severity, xmlTextReaderLocatorPtr) #endif { + XMLErrorWatcher *const watcher = reinterpret_cast(arg); switch (severity) { case XML_PARSER_SEVERITY_VALIDITY_WARNING: @@ -65,6 +66,8 @@ extern "C" break; case XML_PARSER_SEVERITY_ERROR: VSD_DEBUG_MSG(("Found xml parser severity error %s\n", message)); + if (watcher) + watcher->setError(); break; default: break; @@ -75,10 +78,25 @@ extern "C" } // anonymous namespace -xmlTextReaderPtr xmlReaderForStream(librevenge::RVNGInputStream *input, const char *URL, const char *encoding, int options) +XMLErrorWatcher::XMLErrorWatcher() + : m_error(false) +{ +} + +bool XMLErrorWatcher::isError() const +{ + return m_error; +} + +void XMLErrorWatcher::setError() +{ + m_error = true; +} + +xmlTextReaderPtr xmlReaderForStream(librevenge::RVNGInputStream *input, const char *URL, const char *encoding, int options, XMLErrorWatcher *const watcher) { xmlTextReaderPtr reader = xmlReaderForIO(vsdxInputReadFunc, vsdxInputCloseFunc, (void *)input, URL, encoding, options); - xmlTextReaderSetErrorHandler(reader, vsdxReaderErrorFunc, 0); + xmlTextReaderSetErrorHandler(reader, vsdxReaderErrorFunc, watcher); return reader; } diff --git a/src/lib/libvisio_xml.h b/src/lib/libvisio_xml.h index 3ec7524..298b739 100644 --- a/src/lib/libvisio_xml.h +++ b/src/lib/libvisio_xml.h @@ -21,13 +21,30 @@ namespace libvisio struct Colour; +class XMLErrorWatcher +{ + // disable copying + XMLErrorWatcher(const XMLErrorWatcher &); + XMLErrorWatcher &operator=(const XMLErrorWatcher &); + +public: + XMLErrorWatcher(); + + 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, const char *URL, const char *encoding, - int options); + int options, + XMLErrorWatcher *watcher = 0); Colour xmlStringToColour(const xmlChar *s); Colour xmlStringToColour(const boost::shared_ptr &s); -- cgit v1.2.3