summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Tardon <dtardon@redhat.com>2017-04-20 15:53:34 +0200
committerDavid Tardon <dtardon@redhat.com>2017-04-20 15:53:34 +0200
commit442b4812cf058481e00c186ef738c990e1a50284 (patch)
tree4e5ca4176007106e234cc589b3c761c0f1cfeea1
parent1fb548389f0bab6767bf0f656d15328bca0e35cf (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.cpp7
-rw-r--r--src/lib/ABWXMLHelper.cpp26
-rw-r--r--src/lib/ABWXMLHelper.h17
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