[libxml++] Introduce xmlpp::wrapped_exception
- From: Kjell Ahlstedt <kjellahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libxml++] Introduce xmlpp::wrapped_exception
- Date: Thu, 27 Aug 2015 16:11:52 +0000 (UTC)
commit 128615309454dc75ffcb9eaf83fe1188e35b5dfe
Author: Daniel Trebbien <dtrebbien gmail com>
Date: Thu Aug 27 16:42:45 2015 +0200
Introduce xmlpp::wrapped_exception
This is an internal class which is used by SaxParser and Validator to
save the exception object thrown by a handler method when the exception
does not derive from xmlpp::exception (e.g. std::exception). The Raise()
method of xmlpp::wrapped_exception calls std::rethrow_exception() to
rethrow the exception object thrown by the handler method.
Catching any exception object thrown by a handler method is important in
ensuring that we are able to reset the internal state, and, in the case
of SaxParser::parse(), that we restore the old _xmlSAXHandler pointer so
that we do not double-free the _xmlSAXHandler object held by SaxParser.
Fixes Bug 753570 - “double free or corruption” if a std::exception is thrown
https://bugzilla.gnome.org/show_bug.cgi?id=753570
.gitignore | 8 +
Makefile.am | 3 +-
configure.ac | 1 +
libxml++/exceptions/wrapped_exception.cc | 42 +++
libxml++/exceptions/wrapped_exception.h | 43 +++
libxml++/parsers/parser.cc | 5 +
libxml++/parsers/saxparser.cc | 55 ++++-
libxml++/validators/validator.cc | 9 +
tests/Makefile.am | 30 ++
.../main.cc | 80 +++++
tests/saxparser_parse_double_free/main.cc | 321 ++++++++++++++++++++
.../main.cc | 76 +++++
12 files changed, 671 insertions(+), 2 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 270b5bf..b12c415 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,6 +68,7 @@ stamp-h?
/examples/test-suite.log
# macros
+/macros/compile
/macros/compile-binding.am
/macros/config.guess
/macros/config.sub
@@ -83,3 +84,10 @@ stamp-h?
/macros/ltversion.m4
/macros/lt~obsolete.m4
/macros/missing
+/macros/test-driver
+
+# tests
+/tests/*/test
+/tests/*/test.log
+/tests/*/test.trs
+/tests/test-suite.log
diff --git a/Makefile.am b/Makefile.am
index 69f5336..4483936 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = . examples
+SUBDIRS = . examples tests
ACLOCAL_AMFLAGS = -I macros ${ACLOCAL_FLAGS}
DISTCHECK_CONFIGURE_FLAGS = --enable-warnings=fatal
@@ -82,6 +82,7 @@ cc_sources = libxml++/attribute.cc \
libxml++/exceptions/parse_error.cc \
libxml++/exceptions/validity_error.cc \
libxml++/exceptions/internal_error.cc \
+ libxml++/exceptions/wrapped_exception.cc \
libxml++/io/istreamparserinputbuffer.cc \
libxml++/io/outputbuffer.cc \
libxml++/io/ostreamoutputbuffer.cc \
diff --git a/configure.ac b/configure.ac
index 42379fd..8ecc05d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -61,6 +61,7 @@ AC_DEFINE([LIBXMLCPP_EXCEPTIONS_ENABLED],[1], [This is always set. This is only
AC_CONFIG_FILES([Makefile
examples/Makefile
+ tests/Makefile
docs/reference/Doxyfile
MSVC_Net2005/libxml++/libxml++.rc
MSVC_Net2008/libxml++/libxml++.rc
diff --git a/libxml++/exceptions/wrapped_exception.cc b/libxml++/exceptions/wrapped_exception.cc
new file mode 100644
index 0000000..8799e74
--- /dev/null
+++ b/libxml++/exceptions/wrapped_exception.cc
@@ -0,0 +1,42 @@
+/* Copyright (C) 2015 The libxml++ development team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "wrapped_exception.h"
+
+namespace xmlpp
+{
+
+wrapped_exception::wrapped_exception(std::exception_ptr exception_ptr)
+ : exception("Wrapped exception"), exception_ptr_(exception_ptr)
+{
+}
+
+wrapped_exception::~wrapped_exception() noexcept
+{
+}
+
+void wrapped_exception::Raise() const
+{
+ std::rethrow_exception(exception_ptr_);
+}
+
+exception* wrapped_exception::Clone() const
+{
+ return new wrapped_exception(exception_ptr_);
+}
+
+} // namespace xmlpp
diff --git a/libxml++/exceptions/wrapped_exception.h b/libxml++/exceptions/wrapped_exception.h
new file mode 100644
index 0000000..0653842
--- /dev/null
+++ b/libxml++/exceptions/wrapped_exception.h
@@ -0,0 +1,43 @@
+/* Copyright (C) 2015 The libxml++ development team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __LIBXMLPP_WRAPPED_EXCEPTION_H
+#define __LIBXMLPP_WRAPPED_EXCEPTION_H
+
+#include <exception>
+
+#include <libxml++/exceptions/exception.h>
+
+namespace xmlpp
+{
+
+class wrapped_exception : public exception
+{
+public:
+ explicit wrapped_exception(std::exception_ptr exception_ptr);
+ ~wrapped_exception() noexcept override;
+
+ void Raise() const override;
+ exception* Clone() const override;
+
+private:
+ std::exception_ptr exception_ptr_;
+};
+
+} // namespace xmlpp
+
+#endif // __LIBXMLPP_WRAPPED_EXCEPTION_H
diff --git a/libxml++/parsers/parser.cc b/libxml++/parsers/parser.cc
index 34ad6e4..bd3865c 100644
--- a/libxml++/parsers/parser.cc
+++ b/libxml++/parsers/parser.cc
@@ -8,6 +8,7 @@
// because it temporarily undefines G_DISABLE_DEPRECATED while it includes glib.h.
#include <glibmm/threads.h> // For Glib::Threads::Mutex. Needed until the next API/ABI break.
+#include "libxml++/exceptions/wrapped_exception.h"
#include "libxml++/parsers/parser.h"
#include <libxml/parser.h>
@@ -350,6 +351,10 @@ void Parser::callback_error_or_warning(MsgType msg_type, void* ctx,
{
parser->handleException(e);
}
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
}
}
}
diff --git a/libxml++/parsers/saxparser.cc b/libxml++/parsers/saxparser.cc
index e89f1df..17531b2 100644
--- a/libxml++/parsers/saxparser.cc
+++ b/libxml++/parsers/saxparser.cc
@@ -7,6 +7,7 @@
* 2002/01/21 Valentin Rusu - added CDATA handlers
*/
+#include "libxml++/exceptions/wrapped_exception.h"
#include "libxml++/parsers/saxparser.h"
#include "libxml++/nodes/element.h"
#include "libxml++/keepblanks.h"
@@ -384,7 +385,11 @@ xmlEntityPtr SaxParserCallback::get_entity(void* context, const xmlChar* name)
{
parser->handleException(e);
}
-
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
+
return result;
}
@@ -406,6 +411,10 @@ void SaxParserCallback::entity_decl(void* context, const xmlChar* name, int type
{
parser->handleException(e);
}
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
}
void SaxParserCallback::start_document(void* context)
@@ -421,6 +430,10 @@ void SaxParserCallback::start_document(void* context)
{
parser->handleException(e);
}
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
}
void SaxParserCallback::end_document(void* context)
@@ -439,6 +452,10 @@ void SaxParserCallback::end_document(void* context)
{
parser->handleException(e);
}
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
}
void SaxParserCallback::start_element(void* context,
@@ -463,6 +480,10 @@ void SaxParserCallback::start_element(void* context,
{
parser->handleException(e);
}
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
}
void SaxParserCallback::end_element(void* context, const xmlChar* name)
@@ -478,6 +499,10 @@ void SaxParserCallback::end_element(void* context, const xmlChar* name)
{
parser->handleException(e);
}
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
}
void SaxParserCallback::characters(void * context, const xmlChar* ch, int len)
@@ -499,6 +524,10 @@ void SaxParserCallback::characters(void * context, const xmlChar* ch, int len)
{
parser->handleException(e);
}
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
}
void SaxParserCallback::comment(void* context, const xmlChar* value)
@@ -514,6 +543,10 @@ void SaxParserCallback::comment(void* context, const xmlChar* value)
{
parser->handleException(e);
}
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
}
void SaxParserCallback::warning(void* context, const char* fmt, ...)
@@ -536,6 +569,10 @@ void SaxParserCallback::warning(void* context, const char* fmt, ...)
{
parser->handleException(e);
}
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
}
void SaxParserCallback::error(void* context, const char* fmt, ...)
@@ -561,6 +598,10 @@ void SaxParserCallback::error(void* context, const char* fmt, ...)
{
parser->handleException(e);
}
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
}
void SaxParserCallback::fatal_error(void* context, const char* fmt, ...)
@@ -583,6 +624,10 @@ void SaxParserCallback::fatal_error(void* context, const char* fmt, ...)
{
parser->handleException(e);
}
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
}
void SaxParserCallback::cdata_block(void* context, const xmlChar* value, int len)
@@ -603,6 +648,10 @@ void SaxParserCallback::cdata_block(void* context, const xmlChar* value, int len
{
parser->handleException(e);
}
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
}
void SaxParserCallback::internal_subset(void* context, const xmlChar* name,
@@ -622,6 +671,10 @@ void SaxParserCallback::internal_subset(void* context, const xmlChar* name,
{
parser->handleException(e);
}
+ catch(...)
+ {
+ parser->handleException(wrapped_exception(std::current_exception()));
+ }
}
} // namespace xmlpp
diff --git a/libxml++/validators/validator.cc b/libxml++/validators/validator.cc
index 3323e19..220d459 100644
--- a/libxml++/validators/validator.cc
+++ b/libxml++/validators/validator.cc
@@ -5,6 +5,7 @@
* included with libxml++ as the file COPYING.
*/
+#include "libxml++/exceptions/wrapped_exception.h"
#include "libxml++/validators/validator.h"
#include <libxml/parser.h>
@@ -114,6 +115,10 @@ void Validator::callback_validity_error(void* valid_, const char* msg, ...)
{
validator->handleException(e);
}
+ catch(...)
+ {
+ validator->handleException(wrapped_exception(std::current_exception()));
+ }
}
}
@@ -139,6 +144,10 @@ void Validator::callback_validity_warning(void* valid_, const char* msg, ...)
{
validator->handleException(e);
}
+ catch(...)
+ {
+ validator->handleException(wrapped_exception(std::current_exception()));
+ }
}
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..96bfe23
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,30 @@
+## Copyright (C) 2015 The libxml++ development team
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -I. $(LIBXMLXX_CFLAGS)
+AM_CXXFLAGS = $(LIBXMLXX_WXXFLAGS)
+LDADD = $(top_builddir)/libxml++/libxml++-$(LIBXMLXX_API_VERSION).la $(LIBXMLXX_LIBS)
+
+check_PROGRAMS = \
+ saxparser_chunk_parsing_inconsistent_state/test \
+ saxparser_parse_double_free/test \
+ saxparser_parse_stream_inconsistent_state/test
+
+TESTS = $(check_PROGRAMS)
+
+saxparser_chunk_parsing_inconsistent_state_test_SOURCES = saxparser_chunk_parsing_inconsistent_state/main.cc
+saxparser_parse_double_free_test_SOURCES = saxparser_parse_double_free/main.cc
+saxparser_parse_stream_inconsistent_state_test_SOURCES = saxparser_parse_stream_inconsistent_state/main.cc
diff --git a/tests/saxparser_chunk_parsing_inconsistent_state/main.cc
b/tests/saxparser_chunk_parsing_inconsistent_state/main.cc
new file mode 100644
index 0000000..7e5a636
--- /dev/null
+++ b/tests/saxparser_chunk_parsing_inconsistent_state/main.cc
@@ -0,0 +1,80 @@
+/* Copyright (C) 2015 The libxml++ development team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <cstdlib>
+#include <glibmm.h>
+#include <sstream>
+#include <stdexcept>
+
+#include <libxml++/libxml++.h>
+
+class MySaxParser : public xmlpp::SaxParser
+{
+protected:
+ void on_start_document() override
+ {
+ throw std::runtime_error("some custom runtime exception");
+ }
+ void on_error(const Glib::ustring& text) override
+ {
+ throw std::runtime_error("on_error() called");
+ }
+};
+
+int main()
+{
+ Glib::init();
+
+ {
+ MySaxParser parser;
+
+ bool exceptionThrown = false;
+ try
+ {
+ parser.parse_chunk("<?");
+ parser.finish_chunk_parsing();
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "on_error() called");
+ }
+ g_assert_true(exceptionThrown);
+
+ // Try parsing a stream now.
+ exceptionThrown = false;
+ try
+ {
+ std::stringstream ss("<root></root>");
+ parser.parse_stream(ss);
+ }
+ catch(const xmlpp::parse_error& e)
+ {
+ // An "Attempt to start a second parse while a parse is in progress." parse
+ // error should not have been thrown.
+ g_assert_not_reached();
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "some custom runtime exception");
+ }
+ g_assert_true(exceptionThrown);
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/saxparser_parse_double_free/main.cc b/tests/saxparser_parse_double_free/main.cc
new file mode 100644
index 0000000..67dacd8
--- /dev/null
+++ b/tests/saxparser_parse_double_free/main.cc
@@ -0,0 +1,321 @@
+/* Copyright (C) 2015 The libxml++ development team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <cstdlib>
+#include <glibmm.h>
+#include <stdexcept>
+
+#include <libxml++/libxml++.h>
+
+
+class OnCdataBlockTestParser : public xmlpp::SaxParser
+{
+protected:
+ void on_cdata_block(const Glib::ustring& text) override
+ {
+ g_assert_cmpstr(text.c_str(), ==, "some CDATA");
+ throw std::runtime_error("on_cdata_block runtime exception");
+ }
+};
+
+void test_on_cdata_block()
+{
+ OnCdataBlockTestParser parser;
+ bool exceptionThrown = false;
+ try
+ {
+ parser.parse_memory("<root><![CDATA[some CDATA]]></root>");
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "on_cdata_block runtime exception");
+ }
+ g_assert_true(exceptionThrown);
+}
+
+
+class OnCharactersTestParser : public xmlpp::SaxParser
+{
+protected:
+ void on_characters(const Glib::ustring& characters) override
+ {
+ g_assert_cmpstr(characters.c_str(), ==, "abc");
+ throw std::runtime_error("on_characters runtime exception");
+ }
+};
+
+void test_on_characters()
+{
+ OnCharactersTestParser parser;
+ bool exceptionThrown = false;
+ try
+ {
+ parser.parse_memory("<root>abc</root>");
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "on_characters runtime exception");
+ }
+ g_assert_true(exceptionThrown);
+}
+
+
+class OnCommentTestParser : public xmlpp::SaxParser
+{
+protected:
+ void on_comment(const Glib::ustring& text) override
+ {
+ g_assert_cmpstr(text.c_str(), ==, "a comment");
+ throw std::runtime_error("on_comment runtime exception");
+ }
+};
+
+void test_on_comment()
+{
+ OnCommentTestParser parser;
+ bool exceptionThrown = false;
+ try
+ {
+ parser.parse_memory("<root><!--a comment--></root>");
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "on_comment runtime exception");
+ }
+ g_assert_true(exceptionThrown);
+}
+
+
+class OnEndDocumentTestParser : public xmlpp::SaxParser
+{
+protected:
+ void on_end_document() override
+ {
+ throw std::runtime_error("on_end_document runtime exception");
+ }
+};
+
+void test_on_end_document()
+{
+ OnEndDocumentTestParser parser;
+ bool exceptionThrown = false;
+ try
+ {
+ parser.parse_memory("<root></root>");
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "on_end_document runtime exception");
+ }
+ g_assert_true(exceptionThrown);
+}
+
+
+class OnEndElementTestParser : public xmlpp::SaxParser
+{
+protected:
+ void on_end_element(const Glib::ustring& name) override
+ {
+ g_assert_cmpstr(name.c_str(), ==, "a:root");
+ throw std::runtime_error("on_end_element runtime exception");
+ }
+};
+
+void test_on_end_element()
+{
+ OnEndElementTestParser parser;
+ bool exceptionThrown = false;
+ try
+ {
+ parser.parse_memory("<a:root xmlns:a=\"urn:test\"></a:root>");
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "on_end_element runtime exception");
+ }
+ g_assert_true(exceptionThrown);
+}
+
+
+class OnEntityDeclarationTestParser : public xmlpp::SaxParser
+{
+protected:
+ void on_entity_declaration(const Glib::ustring& name, xmlpp::XmlEntityType type, const Glib::ustring&
publicId, const Glib::ustring& systemId, const Glib::ustring& content) override
+ {
+ g_assert_cmpstr(name.c_str(), ==, "number");
+ g_assert_cmpstr(content.c_str(), ==, "42");
+ throw std::runtime_error("on_entity_declaration runtime exception");
+ }
+};
+
+void test_on_entity_declaration()
+{
+ OnEntityDeclarationTestParser parser;
+ bool exceptionThrown = false;
+ try
+ {
+ parser.parse_memory("<!DOCTYPE MyDocument [<!ENTITY number \"42\">]><root></root>");
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "on_entity_declaration runtime exception");
+ }
+ g_assert_true(exceptionThrown);
+}
+
+
+class OnErrorTestParser : public xmlpp::SaxParser
+{
+protected:
+ void on_error(const Glib::ustring& text) override
+ {
+ throw std::runtime_error("on_error runtime exception");
+ }
+};
+
+void test_on_error()
+{
+ OnErrorTestParser parser;
+ bool exceptionThrown = false;
+ try
+ {
+ parser.parse_memory("<root>&unknown;</root>");
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "on_error runtime exception");
+ }
+ g_assert_true(exceptionThrown);
+}
+
+
+class OnGetEntityTestParser : public xmlpp::SaxParser
+{
+public:
+ OnGetEntityTestParser()
+ : xmlpp::SaxParser(true)
+ {
+ }
+protected:
+ _xmlEntity* on_get_entity(const Glib::ustring& name) override
+ {
+ g_assert_cmpstr(name.c_str(), ==, "number");
+ throw std::runtime_error("on_get_entity runtime exception");
+ }
+};
+
+void test_on_get_entity()
+{
+ OnGetEntityTestParser parser;
+ bool exceptionThrown = false;
+ try
+ {
+ parser.parse_memory("<!DOCTYPE MyDocument [<!ENTITY number \"42\">]><root>&number;</root>");
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "on_get_entity runtime exception");
+ }
+ g_assert_true(exceptionThrown);
+}
+
+
+class OnStartDocumentTestParser : public xmlpp::SaxParser
+{
+protected:
+ void on_start_document() override
+ {
+ throw std::runtime_error("on_start_document runtime exception");
+ }
+};
+
+void test_on_start_document()
+{
+ OnStartDocumentTestParser parser;
+ bool exceptionThrown = false;
+ try
+ {
+ parser.parse_memory("<root></root>");
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "on_start_document runtime exception");
+ }
+ g_assert_true(exceptionThrown);
+}
+
+
+class OnStartElementTestParser : public xmlpp::SaxParser
+{
+protected:
+ void on_start_element(const Glib::ustring& name, const xmlpp::SaxParser::AttributeList& attributes)
override
+ {
+ g_assert_cmpstr(name.c_str(), ==, "b:root");
+ g_assert_cmpint(attributes.size(), ==, 2);
+ throw std::runtime_error("on_start_element runtime exception");
+ }
+};
+
+void test_on_start_element()
+{
+ OnStartElementTestParser parser;
+ bool exceptionThrown = false;
+ try
+ {
+ parser.parse_memory("<b:root xmlns:b=\"urn:test\" someattr=\"test\"></b:root>");
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "on_start_element runtime exception");
+ }
+ g_assert_true(exceptionThrown);
+}
+
+
+int main()
+{
+ Glib::init();
+
+ test_on_cdata_block();
+ test_on_characters();
+ test_on_comment();
+ test_on_end_document();
+ test_on_end_element();
+ test_on_entity_declaration();
+ test_on_error();
+ // TODO test on_fatal_error()
+ // This is not currently possible because the fatalError handler is never called;
+ // error is called for all errors.
+ // http://xmlsoft.org/html/libxml-parser.html#fatalErrorSAXFunc
+ test_on_get_entity();
+ // TODO test on_internal_subset()
+ test_on_start_document();
+ test_on_start_element();
+ // TODO test on_warning(), on_validity_error(), on_validity_warning()
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/saxparser_parse_stream_inconsistent_state/main.cc
b/tests/saxparser_parse_stream_inconsistent_state/main.cc
new file mode 100644
index 0000000..ea8cf44
--- /dev/null
+++ b/tests/saxparser_parse_stream_inconsistent_state/main.cc
@@ -0,0 +1,76 @@
+/* Copyright (C) 2015 The libxml++ development team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <cstdlib>
+#include <glibmm.h>
+#include <sstream>
+#include <stdexcept>
+
+#include <libxml++/libxml++.h>
+
+class MySaxParser : public xmlpp::SaxParser
+{
+protected:
+ void on_start_document() override
+ {
+ throw std::runtime_error("some custom runtime exception");
+ }
+};
+
+int main()
+{
+ Glib::init();
+
+ {
+ MySaxParser parser;
+
+ bool exceptionThrown = false;
+ try
+ {
+ std::stringstream ss("<root></root>");
+ parser.parse_stream(ss);
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "some custom runtime exception");
+ }
+ g_assert_true(exceptionThrown);
+
+ // Try parsing a different stream.
+ exceptionThrown = false;
+ try
+ {
+ std::stringstream ss("<root></root>");
+ parser.parse_stream(ss);
+ }
+ catch(const xmlpp::parse_error& e)
+ {
+ // An "Attempt to start a second parse while a parse is in progress." parse
+ // error should not have been thrown.
+ g_assert_not_reached();
+ }
+ catch(const std::runtime_error& e)
+ {
+ exceptionThrown = true;
+ g_assert_cmpstr(e.what(), ==, "some custom runtime exception");
+ }
+ g_assert_true(exceptionThrown);
+ }
+
+ return EXIT_SUCCESS;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]