[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();
+}

Reply via email to