summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Tardon <dtardon@redhat.com>2015-07-20 18:35:56 +0200
committerDavid Tardon <dtardon@redhat.com>2015-07-20 18:35:56 +0200
commitc2031ad6125b4fcd8202778e74b58235cd419f69 (patch)
tree469cc7d3876ec5df18c535e4c7e927b1f364118a
parent5b75213bedc88d6df1d95611521a913ad97a4bdc (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.cpp9
-rw-r--r--src/lib/libvisio_xml.cpp26
-rw-r--r--src/lib/libvisio_xml.h19
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);