diff options
author | David Tardon <dtardon@redhat.com> | 2015-07-20 18:35:56 +0200 |
---|---|---|
committer | David Tardon <dtardon@redhat.com> | 2015-07-20 18:35:56 +0200 |
commit | c2031ad6125b4fcd8202778e74b58235cd419f69 (patch) | |
tree | 469cc7d3876ec5df18c535e4c7e927b1f364118a | |
parent | 5b75213bedc88d6df1d95611521a913ad97a4bdc (diff) |
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
-rw-r--r-- | src/lib/VSDXMetaData.cpp | 9 | ||||
-rw-r--r-- | src/lib/libvisio_xml.cpp | 26 | ||||
-rw-r--r-- | 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<xmlTextReader> 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<XMLErrorWatcher *>(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<xmlChar> &s); |