[This patch is on the git-only branch roland/pr59392.] As described in http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59392, this bug looks to have been present since 4.2 originally introduced support for ARM EABI-based C++ exception handling. I'd like to put this fix on trunk and 4.8, and don't personally care about older versions but the same fix should apply to all versions still being maintained.
The nature of the bug is quite straightforward: it's an unconditional null pointer dereference in the code path for an unexpected throw done inside a user-supplied handler for unexpected exceptions. I'm not really sure if there are other ways to make it manifest. Mark Seaborn is responsible for identifying the fix, which mimics the similar code for the non-EABI implementation (and copies its comment). I filled it out with a regression test. (We're both covered by Google's blanket copyright assignment.) No regressions in 'make check-c++' on arm-linux-gnueabihf. Ok for trunk and 4.8? Thanks, Roland libstdc++-v3/ 2013-12-06 Roland McGrath <mcgra...@google.com> Mark Seaborn <mseab...@google.com> PR libstdc++/59392 * libsupc++/eh_call.cc (__cxa_call_unexpected): Call __do_catch with the address of a null pointer, not with a null pointer to pointer. Copy comment for this case from eh_personality.cc:__cxa_call_unexpected. * testsuite/18_support/bad_exception/59392.cc: New file. --- a/libstdc++-v3/libsupc++/eh_call.cc +++ b/libstdc++-v3/libsupc++/eh_call.cc @@ -140,7 +140,11 @@ __cxa_call_unexpected(void* exc_obj_in) &new_ptr) != ctm_failed) __throw_exception_again; - if (catch_type->__do_catch(&bad_exc, 0, 1)) + // If the exception spec allows std::bad_exception, throw that. + // We don't have a thrown object to compare against, but since + // bad_exception doesn't have virtual bases, that's OK; just pass NULL. + void* obj = NULL; + if (catch_type->__do_catch(&bad_exc, &obj, 1)) bad_exception_allowed = true; } --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/bad_exception/59392.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2013 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, 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 General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <exception> +#include <cstdlib> + +class expected {}; +class unexpected {}; +class from_handler {}; + +static void func_with_exception_spec() throw(expected) +{ + throw unexpected(); +} + +static void unexpected_handler() +{ + throw from_handler(); +} + +static void terminate_handler() +{ + exit(0); +} + +// libstdc++/59392 +int main() +{ + std::set_unexpected(unexpected_handler); + std::set_terminate(terminate_handler); + try { + func_with_exception_spec(); + } catch (expected&) { + abort(); + } + abort(); +}