[libxml++/libxml++-2-40] Work around some platforms' lack of support for std::exception_ptr
- From: Kjell Ahlstedt <kjellahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libxml++/libxml++-2-40] Work around some platforms' lack of support for std::exception_ptr
- Date: Tue, 27 Oct 2015 15:19:27 +0000 (UTC)
commit 4ec9236770c3918ef4393e37ce6a269b21b95ab7
Author: Daniel Trebbien <dtrebbien gmail com>
Date: Mon Oct 26 18:46:28 2015 +0100
Work around some platforms' lack of support for std::exception_ptr
* libxml++/exceptions/wrapped_exception.[cc|h]: Declare the wrapped_exception
class only if LIBXMLXX_HAVE_EXCEPTION_PTR is defined.
* libxml++/parsers/parser.[cc|h]:
* libxml++/parsers/saxparser.cc: Add Parser::handle_exception(), and call
it instead the handleException().
* libxml++/validators/validator.[cc|h]: Add Validator::handle_exception(),
and call it instead the handleException().
* tests/saxparser_chunk_parsing_inconsistent_state/main.cc:
* tests/saxparser_parse_double_free/main.cc:
* tests/saxparser_parse_stream_inconsistent_state/main.cc: Catch
xmlpp::exception, if LIBXMLXX_HAVE_EXCEPTION_PTR is not defined.
Bug #757042.
Kjell Ahlstedt <kjell ahlstedt bredband net> added handle_exception() and
modified Daniel Trebbien's patch to fit with the previous commit.
libxml++/exceptions/wrapped_exception.cc | 4 +
libxml++/exceptions/wrapped_exception.h | 11 +-
libxml++/parsers/parser.cc | 44 +++++++-
libxml++/parsers/parser.h | 4 +
libxml++/parsers/saxparser.cc | 104 +++++---------------
libxml++/validators/validator.cc | 58 +++++++++---
libxml++/validators/validator.h | 4 +
.../main.cc | 13 ++-
tests/saxparser_parse_double_free/main.cc | 46 ++++++++-
.../main.cc | 13 ++-
10 files changed, 192 insertions(+), 109 deletions(-)
---
diff --git a/libxml++/exceptions/wrapped_exception.cc b/libxml++/exceptions/wrapped_exception.cc
index 8799e74..e82dd70 100644
--- a/libxml++/exceptions/wrapped_exception.cc
+++ b/libxml++/exceptions/wrapped_exception.cc
@@ -20,6 +20,8 @@
namespace xmlpp
{
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
+
wrapped_exception::wrapped_exception(std::exception_ptr exception_ptr)
: exception("Wrapped exception"), exception_ptr_(exception_ptr)
{
@@ -39,4 +41,6 @@ exception* wrapped_exception::Clone() const
return new wrapped_exception(exception_ptr_);
}
+#endif // LIBXMLXX_HAVE_EXCEPTION_PTR
+
} // namespace xmlpp
diff --git a/libxml++/exceptions/wrapped_exception.h b/libxml++/exceptions/wrapped_exception.h
index 6fa7bac..3738680 100644
--- a/libxml++/exceptions/wrapped_exception.h
+++ b/libxml++/exceptions/wrapped_exception.h
@@ -21,17 +21,14 @@
#include <exception>
#include <libxml++/exceptions/exception.h>
+#include <libxml++config.h>
namespace xmlpp
{
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-//TODO: At the next ABI break, consider changing
-// exception* exception_;
-// to
-// std::exception_ptr exception_ptr_;
-// in xmlpp::Parser and xmlpp::Validator, and removing xmlpp::wrapped_exception.
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
/** Helper class for propagating an exception through C code.
* Should not be used by applications.
*
@@ -51,6 +48,8 @@ private:
};
#endif //DOXYGEN_SHOULD_SKIP_THIS
+#endif // LIBXMLXX_HAVE_EXCEPTION_PTR
+
} // namespace xmlpp
#endif // __LIBXMLPP_WRAPPED_EXCEPTION_H
diff --git a/libxml++/parsers/parser.cc b/libxml++/parsers/parser.cc
index bd3865c..b96fe90 100644
--- a/libxml++/parsers/parser.cc
+++ b/libxml++/parsers/parser.cc
@@ -347,13 +347,9 @@ void Parser::callback_error_or_warning(MsgType msg_type, void* ctx,
break;
}
}
- catch(const exception& e)
+ catch (...)
{
- parser->handleException(e);
- }
- catch(...)
- {
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
}
}
@@ -370,6 +366,42 @@ void Parser::handleException(const exception& e)
//release_underlying();
}
+void Parser::handle_exception()
+{
+ delete exception_;
+ exception_ = nullptr;
+
+ try
+ {
+ throw; // Rethrow current exception
+ }
+ catch (const exception& e)
+ {
+ exception_ = e.Clone();
+ }
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
+ catch (...)
+ {
+ exception_ = new wrapped_exception(std::current_exception());
+ }
+#else
+ catch (const std::exception& e)
+ {
+ exception_ = new exception(e.what());
+ }
+ catch (...)
+ {
+ exception_ = new exception("An exception was thrown that is not derived from std::exception or
xmlpp::exception.\n"
+ "It could not be caught and rethrown because this platform does not support std::exception_ptr.");
+ }
+#endif
+
+ if (context_)
+ xmlStopParser(context_);
+
+ //release_underlying();
+}
+
void Parser::check_for_exception()
{
check_for_validity_messages();
diff --git a/libxml++/parsers/parser.h b/libxml++/parsers/parser.h
index 96034af..97c49df 100644
--- a/libxml++/parsers/parser.h
+++ b/libxml++/parsers/parser.h
@@ -162,7 +162,11 @@ protected:
virtual void on_validity_error(const Glib::ustring& message);
virtual void on_validity_warning(const Glib::ustring& message);
+ //TODO: When we can break ABI/API, remove handleException() and make
+ // handle_exception() virtual.
virtual void handleException(const exception& e);
+ /// To be called in an exception handler.
+ void handle_exception();
virtual void check_for_exception();
//TODO: In a future API/ABI-break, change the name of this function to
diff --git a/libxml++/parsers/saxparser.cc b/libxml++/parsers/saxparser.cc
index adb2570..b7cf5ab 100644
--- a/libxml++/parsers/saxparser.cc
+++ b/libxml++/parsers/saxparser.cc
@@ -381,13 +381,9 @@ xmlEntityPtr SaxParserCallback::get_entity(void* context, const xmlChar* name)
{
result = parser->on_get_entity((const char*)name);
}
- catch(const exception& e)
+ catch (...)
{
- parser->handleException(e);
- }
- catch(...)
- {
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
return result;
@@ -407,13 +403,9 @@ void SaxParserCallback::entity_decl(void* context, const xmlChar* name, int type
( systemId ? Glib::ustring((const char*)systemId) : ""),
( content ? Glib::ustring((const char*)content) : "") );
}
- catch(const exception& e)
- {
- parser->handleException(e);
- }
- catch(...)
+ catch (...)
{
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
}
@@ -426,13 +418,9 @@ void SaxParserCallback::start_document(void* context)
{
parser->on_start_document();
}
- catch(const exception& e)
+ catch (...)
{
- parser->handleException(e);
- }
- catch(...)
- {
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
}
@@ -448,13 +436,9 @@ void SaxParserCallback::end_document(void* context)
{
parser->on_end_document();
}
- catch(const exception& e)
+ catch (...)
{
- parser->handleException(e);
- }
- catch(...)
- {
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
}
@@ -476,13 +460,9 @@ void SaxParserCallback::start_element(void* context,
{
parser->on_start_element(Glib::ustring((const char*) name), attributes);
}
- catch(const exception& e)
- {
- parser->handleException(e);
- }
- catch(...)
+ catch (...)
{
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
}
@@ -495,13 +475,9 @@ void SaxParserCallback::end_element(void* context, const xmlChar* name)
{
parser->on_end_element(Glib::ustring((const char*) name));
}
- catch(const exception& e)
+ catch (...)
{
- parser->handleException(e);
- }
- catch(...)
- {
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
}
@@ -520,13 +496,9 @@ void SaxParserCallback::characters(void * context, const xmlChar* ch, int len)
reinterpret_cast<const char *>(ch),
reinterpret_cast<const char *>(ch + len) ) );
}
- catch(const exception& e)
- {
- parser->handleException(e);
- }
- catch(...)
+ catch (...)
{
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
}
@@ -539,13 +511,9 @@ void SaxParserCallback::comment(void* context, const xmlChar* value)
{
parser->on_comment(Glib::ustring((const char*) value));
}
- catch(const exception& e)
- {
- parser->handleException(e);
- }
- catch(...)
+ catch (...)
{
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
}
@@ -565,13 +533,9 @@ void SaxParserCallback::warning(void* context, const char* fmt, ...)
{
parser->on_warning(Glib::ustring(buff));
}
- catch(const exception& e)
+ catch (...)
{
- parser->handleException(e);
- }
- catch(...)
- {
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
}
@@ -594,13 +558,9 @@ void SaxParserCallback::error(void* context, const char* fmt, ...)
{
parser->on_error(Glib::ustring(buff));
}
- catch(const exception& e)
- {
- parser->handleException(e);
- }
- catch(...)
+ catch (...)
{
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
}
@@ -620,13 +580,9 @@ void SaxParserCallback::fatal_error(void* context, const char* fmt, ...)
{
parser->on_fatal_error(Glib::ustring(buff));
}
- catch(const exception& e)
+ catch (...)
{
- parser->handleException(e);
- }
- catch(...)
- {
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
}
@@ -644,13 +600,9 @@ void SaxParserCallback::cdata_block(void* context, const xmlChar* value, int len
reinterpret_cast<const char *>(value),
reinterpret_cast<const char *>(value + len) ) );
}
- catch(const exception& e)
- {
- parser->handleException(e);
- }
- catch(...)
+ catch (...)
{
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
}
@@ -667,13 +619,9 @@ void SaxParserCallback::internal_subset(void* context, const xmlChar* name,
parser->on_internal_subset( Glib::ustring((const char*) name), pid, sid);
}
- catch(const exception& e)
- {
- parser->handleException(e);
- }
- catch(...)
+ catch (...)
{
- parser->handleException(wrapped_exception(std::current_exception()));
+ parser->handle_exception();
}
}
diff --git a/libxml++/validators/validator.cc b/libxml++/validators/validator.cc
index 220d459..8e7a837 100644
--- a/libxml++/validators/validator.cc
+++ b/libxml++/validators/validator.cc
@@ -111,13 +111,9 @@ void Validator::callback_validity_error(void* valid_, const char* msg, ...)
{
validator->on_validity_error(Glib::ustring(buff));
}
- catch(const exception& e)
+ catch (...)
{
- validator->handleException(e);
- }
- catch(...)
- {
- validator->handleException(wrapped_exception(std::current_exception()));
+ validator->handle_exception();
}
}
}
@@ -140,13 +136,9 @@ void Validator::callback_validity_warning(void* valid_, const char* msg, ...)
{
validator->on_validity_warning(Glib::ustring(buff));
}
- catch(const exception& e)
- {
- validator->handleException(e);
- }
- catch(...)
+ catch (...)
{
- validator->handleException(wrapped_exception(std::current_exception()));
+ validator->handle_exception();
}
}
}
@@ -168,6 +160,48 @@ void Validator::handleException(const exception& e)
//release_underlying();
}
+void Validator::handle_exception()
+{
+ delete exception_;
+ exception_ = nullptr;
+
+ try
+ {
+ throw; // Rethrow current exception
+ }
+ catch (const exception& e)
+ {
+ exception_ = e.Clone();
+ }
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
+ catch (...)
+ {
+ exception_ = new wrapped_exception(std::current_exception());
+ }
+#else
+ catch (const std::exception& e)
+ {
+ exception_ = new exception(e.what());
+ }
+ catch (...)
+ {
+ exception_ = new exception("An exception was thrown that is not derived from std::exception or
xmlpp::exception.\n"
+ "It could not be caught and rethrown because this platform does not support std::exception_ptr.");
+ }
+#endif
+
+ // Don't delete the DTD validation context or schema validation context
+ // while validating. It would cause accesses to deallocated memory in libxml2
+ // functions after the return from Validator::callback_validity_...().
+ // Parser::handle_exception() calls xmlStopParser(), but there is no
+ // xmlStopValidator() or similar function to call here.
+ // We don't throw the exception here, since it would have to pass through
+ // C functions. That's not guaranteed to work. It might work, but it depends
+ // on the C compiler and the options used when building libxml2.
+
+ //release_underlying();
+}
+
void Validator::check_for_exception()
{
check_for_validity_messages();
diff --git a/libxml++/validators/validator.h b/libxml++/validators/validator.h
index cdf9f2f..6d4a5d8 100644
--- a/libxml++/validators/validator.h
+++ b/libxml++/validators/validator.h
@@ -37,7 +37,11 @@ protected:
virtual void on_validity_error(const Glib::ustring& message);
virtual void on_validity_warning(const Glib::ustring& message);
+ //TODO: When we can break ABI/API, remove handleException() and make
+ // handle_exception() virtual.
virtual void handleException(const exception& e);
+ /// To be called in an exception handler.
+ void handle_exception();
virtual void check_for_exception();
virtual void check_for_validity_messages();
diff --git a/tests/saxparser_chunk_parsing_inconsistent_state/main.cc
b/tests/saxparser_chunk_parsing_inconsistent_state/main.cc
index 5e34233..136bfb7 100644
--- a/tests/saxparser_chunk_parsing_inconsistent_state/main.cc
+++ b/tests/saxparser_chunk_parsing_inconsistent_state/main.cc
@@ -15,13 +15,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <config.h>
+#include <libxml++/libxml++.h>
+
#include <cstdlib>
#include <glibmm.h>
#include <sstream>
#include <stdexcept>
-#include <libxml++/libxml++.h>
-
class MySaxParser : public xmlpp::SaxParser
{
protected:
@@ -48,7 +49,11 @@ int main()
parser.parse_chunk("<?");
parser.finish_chunk_parsing();
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "on_error() called");
@@ -68,7 +73,11 @@ int main()
// error should not have been thrown.
g_assert_not_reached();
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "some custom runtime exception");
diff --git a/tests/saxparser_parse_double_free/main.cc b/tests/saxparser_parse_double_free/main.cc
index faaf964..e1bd3b6 100644
--- a/tests/saxparser_parse_double_free/main.cc
+++ b/tests/saxparser_parse_double_free/main.cc
@@ -15,13 +15,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <config.h>
+#include <libxml++/libxml++.h>
+
#include <cstdlib>
#include <glibmm.h>
#include <stdexcept>
-#include <libxml++/libxml++.h>
-
-
class OnCdataBlockTestParser : public xmlpp::SaxParser
{
protected:
@@ -40,7 +40,11 @@ void test_on_cdata_block()
{
parser.parse_memory("<root><![CDATA[some CDATA]]></root>");
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "on_cdata_block runtime exception");
@@ -67,7 +71,11 @@ void test_on_characters()
{
parser.parse_memory("<root>abc</root>");
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "on_characters runtime exception");
@@ -94,7 +102,11 @@ void test_on_comment()
{
parser.parse_memory("<root><!--a comment--></root>");
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "on_comment runtime exception");
@@ -120,7 +132,11 @@ void test_on_end_document()
{
parser.parse_memory("<root></root>");
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "on_end_document runtime exception");
@@ -147,7 +163,11 @@ void test_on_end_element()
{
parser.parse_memory("<a:root xmlns:a=\"urn:test\"></a:root>");
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "on_end_element runtime exception");
@@ -177,7 +197,11 @@ void test_on_entity_declaration()
{
parser.parse_memory("<!DOCTYPE MyDocument [<!ENTITY number \"42\">]><root></root>");
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "on_entity_declaration runtime exception");
@@ -203,7 +227,11 @@ void test_on_error()
{
parser.parse_memory("<root>&unknown;</root>");
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "on_error runtime exception");
@@ -235,7 +263,11 @@ void test_on_get_entity()
{
parser.parse_memory("<!DOCTYPE MyDocument [<!ENTITY number \"42\">]><root>&number;</root>");
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "on_get_entity runtime exception");
@@ -261,7 +293,11 @@ void test_on_start_document()
{
parser.parse_memory("<root></root>");
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "on_start_document runtime exception");
@@ -289,7 +325,11 @@ void test_on_start_element()
{
parser.parse_memory("<b:root xmlns:b=\"urn:test\" someattr=\"test\"></b:root>");
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "on_start_element runtime exception");
diff --git a/tests/saxparser_parse_stream_inconsistent_state/main.cc
b/tests/saxparser_parse_stream_inconsistent_state/main.cc
index ea8cf44..4fd1320 100644
--- a/tests/saxparser_parse_stream_inconsistent_state/main.cc
+++ b/tests/saxparser_parse_stream_inconsistent_state/main.cc
@@ -15,13 +15,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <config.h>
+#include <libxml++/libxml++.h>
+
#include <cstdlib>
#include <glibmm.h>
#include <sstream>
#include <stdexcept>
-#include <libxml++/libxml++.h>
-
class MySaxParser : public xmlpp::SaxParser
{
protected:
@@ -44,7 +45,11 @@ int main()
std::stringstream ss("<root></root>");
parser.parse_stream(ss);
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "some custom runtime exception");
@@ -64,7 +69,11 @@ int main()
// error should not have been thrown.
g_assert_not_reached();
}
+#ifdef LIBXMLXX_HAVE_EXCEPTION_PTR
catch(const std::runtime_error& e)
+#else
+ catch(const xmlpp::exception& e)
+#endif
{
exceptionThrown = true;
g_assert_cmpstr(e.what(), ==, "some custom runtime exception");
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]