diff options
author | David Tardon <dtardon@redhat.com> | 2017-05-17 13:27:41 +0200 |
---|---|---|
committer | David Tardon <dtardon@redhat.com> | 2017-05-17 13:27:41 +0200 |
commit | 2a17664d1ce065c75094a05ff29a4feded742aa7 (patch) | |
tree | e09cac8f3cc1cc52d05a3e68e01e7ed8c8da7990 | |
parent | 39a8567ff10e2b3ca4c7a3be0d6604cb881819f4 (diff) |
improve check for stuck XML parser
This fixes regression in parsing some broken documents caused by commit
442b4812cf058481e00c186ef738c990e1a50284 .
Change-Id: Id4afc8b120c72cb77f27c71c3f1452e100f86faf
-rw-r--r-- | src/lib/ABWParser.cpp | 6 | ||||
-rw-r--r-- | src/lib/ABWXMLHelper.cpp | 39 | ||||
-rw-r--r-- | src/lib/ABWXMLHelper.h | 22 |
3 files changed, 47 insertions, 20 deletions
diff --git a/src/lib/ABWParser.cpp b/src/lib/ABWParser.cpp index 16826e2..db3c68c 100644 --- a/src/lib/ABWParser.cpp +++ b/src/lib/ABWParser.cpp @@ -166,12 +166,12 @@ bool libabw::ABWParser::processXmlDocument(librevenge::RVNGInputStream *input) if (!input) return false; - ABWXMLErrorWatcher watcher; + ABWXMLProgressWatcher watcher; auto reader(xmlReaderForStream(input, &watcher)); if (!reader) return false; int ret = xmlTextReaderRead(reader.get()); - while (1 == ret && !watcher.isError()) + while (1 == ret && !watcher.isStuck()) { processXmlNode(reader.get()); ret = xmlTextReaderRead(reader.get()); @@ -179,7 +179,7 @@ bool libabw::ABWParser::processXmlDocument(librevenge::RVNGInputStream *input) if (m_collector) m_collector->endDocument(); - return !watcher.isError(); + return ret == 1 && !watcher.isStuck(); } void libabw::ABWParser::processXmlNode(xmlTextReaderPtr reader) diff --git a/src/lib/ABWXMLHelper.cpp b/src/lib/ABWXMLHelper.cpp index 4295c47..fe8638e 100644 --- a/src/lib/ABWXMLHelper.cpp +++ b/src/lib/ABWXMLHelper.cpp @@ -51,7 +51,7 @@ extern "C" { static void abwxmlReaderErrorFunc(void *arg, const char *, xmlParserSeverities severity, xmlTextReaderLocatorPtr) #endif { - const auto watcher = reinterpret_cast<ABWXMLErrorWatcher *>(arg); + const auto watcher = reinterpret_cast<ABWXMLProgressWatcher *>(arg); switch (severity) { case XML_PARSER_SEVERITY_VALIDITY_WARNING: @@ -66,7 +66,7 @@ extern "C" { case XML_PARSER_SEVERITY_ERROR: ABW_DEBUG_MSG(("Found xml parser severity error %s\n", message)); if (watcher) - watcher->setError(); + watcher->signalError(); break; default: break; @@ -92,29 +92,50 @@ ABWXMLString::operator const char *() const return reinterpret_cast<const char *>(m_xml.get()); } -ABWXMLErrorWatcher::ABWXMLErrorWatcher() - : m_error(false) +ABWXMLProgressWatcher::ABWXMLProgressWatcher() + : m_reader(nullptr) + , m_line(0) + , m_col(0) + , m_wasError(false) + , m_isStuck(false) { } -bool ABWXMLErrorWatcher::isError() const +void ABWXMLProgressWatcher::setReader(xmlTextReaderPtr reader) { - return m_error; + m_reader = reader; } -void ABWXMLErrorWatcher::setError() +bool ABWXMLProgressWatcher::isStuck() const { - m_error = true; + return m_isStuck; +} + +void ABWXMLProgressWatcher::signalError() +{ + if (m_reader && !m_isStuck) + { + const int line = m_line; + const int col = m_col; + const bool checkStuck = m_wasError; + m_wasError = true; + m_line = xmlTextReaderGetParserLineNumber(m_reader); + m_col = xmlTextReaderGetParserColumnNumber(m_reader); + if (checkStuck) + m_isStuck = line == m_line && col == m_col; + } } // xmlTextReader helper function -std::unique_ptr<xmlTextReader, void(*)(xmlTextReaderPtr)> xmlReaderForStream(librevenge::RVNGInputStream *input, ABWXMLErrorWatcher *watcher) +std::unique_ptr<xmlTextReader, void(*)(xmlTextReaderPtr)> xmlReaderForStream(librevenge::RVNGInputStream *input, ABWXMLProgressWatcher *watcher) { std::unique_ptr<xmlTextReader, void(*)(xmlTextReaderPtr)> reader( xmlReaderForIO(abwxmlInputReadFunc, abwxmlInputCloseFunc, (void *)input, 0, 0, XML_PARSE_NOBLANKS|XML_PARSE_NOENT|XML_PARSE_NONET|XML_PARSE_RECOVER), xmlFreeTextReader); + if (watcher) + watcher->setReader(reader.get()); if (reader) xmlTextReaderSetErrorHandler(reader.get(), abwxmlReaderErrorFunc, watcher); return reader; diff --git a/src/lib/ABWXMLHelper.h b/src/lib/ABWXMLHelper.h index 5cd6b2c..b657b19 100644 --- a/src/lib/ABWXMLHelper.h +++ b/src/lib/ABWXMLHelper.h @@ -34,23 +34,29 @@ private: std::shared_ptr<xmlChar> m_xml; }; -class ABWXMLErrorWatcher +class ABWXMLProgressWatcher { - ABWXMLErrorWatcher(const ABWXMLErrorWatcher &) = delete; - ABWXMLErrorWatcher &operator=(const ABWXMLErrorWatcher &) = delete; + ABWXMLProgressWatcher(const ABWXMLProgressWatcher &) = delete; + ABWXMLProgressWatcher &operator=(const ABWXMLProgressWatcher &) = delete; public: - ABWXMLErrorWatcher(); + ABWXMLProgressWatcher(); - bool isError() const; - void setError(); + void setReader(xmlTextReaderPtr reader); + + bool isStuck() const; + void signalError(); private: - bool m_error; + xmlTextReaderPtr m_reader; + int m_line; + int m_col; + bool m_wasError; + bool m_isStuck; }; // create an xmlTextReader pointer from a librevenge::RVNGInputStream pointer -std::unique_ptr<xmlTextReader, void(*)(xmlTextReaderPtr)> xmlReaderForStream(librevenge::RVNGInputStream *input, ABWXMLErrorWatcher *watcher = 0); +std::unique_ptr<xmlTextReader, void(*)(xmlTextReaderPtr)> xmlReaderForStream(librevenge::RVNGInputStream *input, ABWXMLProgressWatcher *watcher = 0); } // namespace libabw |