From patchwork Sun Jan 14 00:05:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julia DeMille X-Patchwork-Id: 84052 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D8D903858421 for ; Sun, 14 Jan 2024 00:06:41 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from luna.jdemille.com (luna.jdemille.com [168.119.233.50]) by sourceware.org (Postfix) with ESMTPS id D0D153858D32; Sun, 14 Jan 2024 00:05:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D0D153858D32 Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=jdemille.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=jdemille.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D0D153858D32 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=168.119.233.50 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1705190760; cv=none; b=HOFE+7lJHmkshYUaBQbeLqwrMtVGO66R4jQ9AMFeJtVjLb/oHw+Uahh3CTqCuYK8GQm6tFI055zDUDtELGkyx0nDQ0YPNjBK6IVLjTDwcx8VaWuNh2hmRNgdV/2frFPkVLJe25wPxIwx9DXARWiLbThQfbadFF6BYnORs500Hzc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1705190760; c=relaxed/simple; bh=ouH3BB5cio/twqNYUdy1ixDioDSEwNFu2/SCo8Ad+Cw=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=QlqTn7juYkcF8nuWxmdVmLLn8rRwWLYlPJ96VYn4msCUAAr7D3ehoGiI0Bl31ze7Meb8IrLf4MIoIg7dRZ8vdj332QDDzUdD6K5f/VJMjl6R20bYcV38OCaX1LR14aG8PGjMLBjQKXh0e/Yj20S8K+21faSq81m1UwkczsEvMCc= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 17F6740BF4; Sun, 14 Jan 2024 00:05:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jdemille.com; s=mc20210101; t=1705190755; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding; bh=TIRBtJaB9upHpKLP/VFHmsHMf5OB4mE5UXZu4GiIZXA=; b=R+BPmxncXTWLYYNt0kZ0lCzCYRXm7jF51srsjFc7oBmT66d7MZS9cXjd+d+JdMsGEf3XG6 Sq5cIQqP2TPMCHJm+hzK4tjVW1rt9pEag4DVnhTcecSD4M77qQgReK7024jt1cpah+pwKU FnRUz96IAPgEob9RCyLuaNP1DQa+Ehgj/IVZI6VJhdgn+Hq4GOGQBHd0lYBRS6ppDwqBe7 WyyoEoHoPrx1f902+EsZMNF6qi/mdR/DDHbwY8i9ClkhZ0eTorpN7yXCXHtY6REwJz3rNg t6FjFYYQRmwQZ0Y4Guj1x7ZT6h0LMChNEL2shr1WPLlU4oX6HLcYf+dEYE6NDHXY/or+Ua KYw0A0sg2bMoZfHU9ShpLwM23u4yQwfTvAa1NnWJuTBDd359VU/ZMA2cctrf2eXIQu9d3Y ThzPhmPksvJqV3Wf/lDNVI3saXzDcx36xMSDcWJkkPyojC3udknf2fuCD5DmxkFrrWQZGI KZiAYqlyKmJsKUiaYh/IpuKyg0oHBfDD2utmGVwO5AHVt2ej1qzaV3M8P5SET4qvOOyDSc 6TappzH24hEnDZwf0a5/ZDC3ho0PE7ndkY61x1TZrQ0s9gX2wHYKZsoihKNjvxAzLCh9Np XaS5bTcT/UGaRzEaGwqzwTwYV33GOk1uw3qgCjrwiHYdcNPDNFFQ0= From: Julia DeMille To: gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org Cc: Julia DeMille Subject: [PATCH] libsupc++: Fix UB terminating on foreign exception Date: Sat, 13 Jan 2024 18:05:27 -0600 Message-ID: <20240114000534.1775261-1-me@jdemille.com> MIME-Version: 1.0 X-Last-TLS-Session-Version: TLSv1.3 X-Spam-Status: No, score=-13.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org 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 --- 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 + * 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 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 #if _GLIBCXX_HOSTED -#include -#include +#include "unwind-cxx.h" #include +#include +#include #include -# include +#include 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);