From: Julia DeMille <me@jdemille.com>
To: gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org
Cc: Julia DeMille <me@jdemille.com>
Subject: [PATCH] libsupc++: Fix UB terminating on foreign exception
Date: Sat, 13 Jan 2024 18:05:27 -0600 [thread overview]
Message-ID: <20240114000534.1775261-1-me@jdemille.com> (raw)
Currently, when std::terminate() is called with a foreign exception
active, since nothing in the path checks whether the exception matches
the `GNUCC++\0` personality, a foreign exception can go into the verbose
terminate handler, and get treated as though it were a C++ exception.
Reflection is attempted, and boom. UB. This patch should eliminate that
UB.
Signed-off-by: Julia DeMille <me@jdemille.com>
---
libstdc++-v3/ChangeLog | 9 +++++++++
libstdc++-v3/libsupc++/eh_type.cc | 11 +++++++++++
libstdc++-v3/libsupc++/vterminate.cc | 25 ++++++++++++++++++++-----
3 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 36257cc4427..bfef0ed8ef1 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,12 @@
+2024-01-13 Julia DeMille <me@jdemille.com>
+ * libsupc++/eh_type.cc (__cxa_current_exception_type):
+ Return NULL if the current exception is not the `GNUCC++\0`
+ personality.
+ * libsupc++/vterminate.cc:
+ Check for both exception header and exception type. If there
+ is an exception header, but no exception type, state in termination
+ message that a foreign exception was active.
+
2024-01-13 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/107466
diff --git a/libstdc++-v3/libsupc++/eh_type.cc b/libstdc++-v3/libsupc++/eh_type.cc
index 03c677b7e13..e0824eab4d4 100644
--- a/libstdc++-v3/libsupc++/eh_type.cc
+++ b/libstdc++-v3/libsupc++/eh_type.cc
@@ -36,9 +36,20 @@ extern "C"
std::type_info *__cxa_current_exception_type () _GLIBCXX_NOTHROW
{
__cxa_eh_globals *globals = __cxa_get_globals ();
+
+ if (!globals)
+ return 0;
+
__cxa_exception *header = globals->caughtExceptions;
+
if (header)
{
+ // It is UB to try and inspect an exception that isn't ours.
+ // This extends to attempting to perform run-time reflection, as the ABI
+ // is unknown.
+ if (!__is_gxx_exception_class (header->unwindHeader.exception_class))
+ return 0;
+
if (__is_dependent_exception (header->unwindHeader.exception_class))
{
__cxa_dependent_exception *de =
diff --git a/libstdc++-v3/libsupc++/vterminate.cc b/libstdc++-v3/libsupc++/vterminate.cc
index 23deeef5289..f931d951526 100644
--- a/libstdc++-v3/libsupc++/vterminate.cc
+++ b/libstdc++-v3/libsupc++/vterminate.cc
@@ -25,11 +25,12 @@
#include <bits/c++config.h>
#if _GLIBCXX_HOSTED
-#include <cstdlib>
-#include <exception>
+#include "unwind-cxx.h"
#include <bits/exception_defines.h>
+#include <cstdio>
+#include <cstdlib>
#include <cxxabi.h>
-# include <cstdio>
+#include <exception>
using namespace std;
using namespace abi;
@@ -51,10 +52,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
terminating = true;
+ __cxa_eh_globals *globals = __cxa_get_globals ();
+ if (!globals)
+ {
+ fputs ("terminate called", stderr);
+ abort ();
+ }
+
// Make sure there was an exception; terminate is also called for an
// attempt to rethrow when there is no suitable exception.
- type_info *t = __cxa_current_exception_type();
- if (t)
+ type_info *t = __cxa_current_exception_type ();
+ __cxa_exception *header = globals->caughtExceptions;
+
+ if (t && header)
{
// Note that "name" is the mangled name.
char const *name = t->name();
@@ -89,6 +99,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
__catch(...) { }
}
+ else if (header)
+ {
+ fputs ("terminate called after a foreign exception was thrown\n",
+ stderr);
+ }
else
fputs("terminate called without an active exception\n", stderr);
--
2.43.0
next reply other threads:[~2024-01-14 0:05 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-14 0:05 Julia DeMille [this message]
2024-01-14 1:17 ` Andrew Pinski
2024-01-14 1:34 ` Julia DeMille
2024-01-14 7:52 ` Jonathan Wakely
2024-01-15 0:51 ` Julia DeMille
2024-01-15 3:39 ` Julia DeMille
2024-01-15 17:31 ` Julia DeMille
2024-04-09 17:24 ` Julia DeMille
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240114000534.1775261-1-me@jdemille.com \
--to=me@jdemille.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=libstdc++@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).