public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
From: Jonathan Wakely <redi@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org
Subject: [gcc r13-3696] libstdc++: fix pointer type exception catch (no RTTI) [PR105387]
Date: Sat,  5 Nov 2022 14:03:42 +0000 (GMT)	[thread overview]
Message-ID: <20221105140342.123933858D26@sourceware.org> (raw)

https://gcc.gnu.org/g:b83f01d0057578ebc1785f858fbfd46cdc210560

commit r13-3696-gb83f01d0057578ebc1785f858fbfd46cdc210560
Author: Jakob Hasse <0xjakob@users.noreply.github.com>
Date:   Tue Apr 26 12:03:47 2022 +0800

    libstdc++: fix pointer type exception catch (no RTTI) [PR105387]
    
    __pbase_type_info::__do_catch(), used to catch pointer type exceptions,
    did not check if the type info object to compare against is a pointer
    type info object before doing a static down-cast to a pointer type info
    object. If RTTI is disabled, this leads to the following situation:
    Since a pointer type info object has additional fields, they would
    end up being undefined if the actual type info object was not a pointer
    type info object.
    
    A simple check has been added before the down-cast happens.
    
    Note that a consequence of this check is that exceptions of type
    pointer-to-member cannot be caught anymore.
    
    In case RTTI is enabled, this does not seem to be a problem because
    RTTI-based checks would run before and prevent running into the bad
    down-cast. Hence, the fix is disabled if RTTI is enabled and exceptions
    of type pointer-to-member can still be caught.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/105387
            * libsupc++/pbase_type_info.cc (__do_catch) [!__cpp_rtti]: Add
            check that the thrown type is actually a pointer.
            * testsuite/18_support/105387.cc: New test.
            * testsuite/18_support/105387_memptr.cc: New test.
    
    Signed-off-by: Jakob Hasse <jakob.hasse@espressif.com>

Diff:
---
 libstdc++-v3/libsupc++/pbase_type_info.cc          |  7 ++-
 libstdc++-v3/testsuite/18_support/105387.cc        | 63 ++++++++++++++++++++++
 libstdc++-v3/testsuite/18_support/105387_memptr.cc | 25 +++++++++
 3 files changed, 94 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/libsupc++/pbase_type_info.cc b/libstdc++-v3/libsupc++/pbase_type_info.cc
index 7e5720b84a3..934e049a4e0 100644
--- a/libstdc++-v3/libsupc++/pbase_type_info.cc
+++ b/libstdc++-v3/libsupc++/pbase_type_info.cc
@@ -74,7 +74,12 @@ __do_catch (const type_info *thr_type,
     // Therefore there must at least be a qualification conversion involved
     // But for that to be valid, our outer pointers must be const qualified.
     return false;
-  
+
+#if !__cpp_rtti
+  if (!thr_type->__is_pointer_p ())
+    return false;
+#endif
+
   const __pbase_type_info *thrown_type =
     static_cast <const __pbase_type_info *> (thr_type);
 
diff --git a/libstdc++-v3/testsuite/18_support/105387.cc b/libstdc++-v3/testsuite/18_support/105387.cc
new file mode 100644
index 00000000000..c4a234523f2
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/105387.cc
@@ -0,0 +1,63 @@
+// { dg-do run }
+
+#include <stdexcept>
+#include <cxxabi.h>
+#include <testsuite_hooks.h>
+
+// Test cases for PR libstdc++/105387
+
+// This test is to trigger undefined behavior if the bug 105387 is present
+// in the code. Note, however, given that the bug is present, this test runs
+// into undefined behavior which can also mean that it passes.
+// It has been observed to fail quite reliably on x86_64-linux-gnu but only
+// fail sporadically on Xtensa, depending on the code placement.
+void portable_test()
+{
+  bool exception_thrown = false;
+  try {
+    throw std::runtime_error("test");
+  } catch (const char *e) {
+    VERIFY(false);
+  } catch (const std::exception &e) {
+    exception_thrown = true;
+  }
+  VERIFY(exception_thrown);
+}
+
+// This test relies on the types defined in the files typeinfo and cxxabi.h
+// It is therefore less portable then the test case above but should be
+// guaranteed to fail if the implementation has the bug 105387.
+//
+// This test case checks that __pbase_type_info::__do_catch() behaves
+// correctly when called with a non-pointer type info object as argument.
+// In particular, __pbase_type_info::__do_catch() should not cast
+// the given type object into a pointer type and try to access the
+// extended fields.
+
+void non_portable_test()
+{
+  // Create a zero-initialized buffer for allocation of the type object
+  unsigned char buffer [sizeof(__cxxabiv1::__fundamental_type_info) * 2] = {};
+
+  // Use placement-new to create the fundamental type info object in the
+  // first half of the buffer. Whenever that type info object will be
+  // casted to a pointer type info object, the extended fields of the
+  // pointer type info object will be in the second half of the buffer
+  // and hence be guaranteed zero.
+  __cxxabiv1::__fundamental_type_info *p_fund_info
+    = new(buffer) __cxxabiv1::__fundamental_type_info("fund_type");
+
+  __cxxabiv1::__pointer_type_info ptr_info("ptr_type", 0, p_fund_info);
+
+  // __do_catch is declared protected in __pointer_type_info, but public in
+  // type_info, so we upcast it here
+  std::type_info *abstract_ptr_info = static_cast<std::type_info*>(&ptr_info);
+  VERIFY(abstract_ptr_info->__do_catch(p_fund_info, 0, 1) == false);
+}
+
+int main()
+{
+  portable_test();
+  non_portable_test();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/18_support/105387_memptr.cc b/libstdc++-v3/testsuite/18_support/105387_memptr.cc
new file mode 100644
index 00000000000..f5612f42929
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/105387_memptr.cc
@@ -0,0 +1,25 @@
+#include <testsuite_hooks.h>
+
+// Test related to PR libstdc++/105387
+// Check that pointer-to-member type exceptions can still be caught with -frtti.
+// { dg-require-effective-target rtti }
+
+void test_catch_ptr_to_member()
+{
+  bool exception_thrown = false;
+  struct X { int i; };
+  try {
+    throw &X::i;
+  }
+  catch (const int X::*) {
+    exception_thrown = true;
+  }
+
+  VERIFY(exception_thrown);
+}
+
+int main()
+{
+  test_catch_ptr_to_member();
+  return 0;
+}

                 reply	other threads:[~2022-11-05 14:03 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20221105140342.123933858D26@sourceware.org \
    --to=redi@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    --cc=libstdc++-cvs@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).