Commit 4ec92367 authored by Daniel Trebbien's avatar Daniel Trebbien Committed by Kjell Ahlstedt

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.
parent a77aef9d
......@@ -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
......@@ -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
......@@ -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();
......
......@@ -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
......
......@@ -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();
}
}
......
......@@ -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();
......
......@@ -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();
......
......@@ -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");
......
......@@ -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");
......
......@@ -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");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment