public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
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


             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).