From: Jakob Hasse <jakob.hasse@espressif.com>
To: "libstdc++@gcc.gnu.org" <libstdc++@gcc.gnu.org>,
gcc-patches <gcc-patches@gcc.gnu.org>
Cc: Ivan Grokhotkov <ivan@espressif.com>,
Anton Maklakov <anton.maklakov@espressif.com>
Subject: [PATCH v3] libstdc++: fix pointer type exception catch [PR105387]
Date: Wed, 25 May 2022 02:29:17 +0000 [thread overview]
Message-ID: <HK0PR04MB253054AE1AD1416F3C9DE016E4D69@HK0PR04MB2530.apcprd04.prod.outlook.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 1386 bytes --]
Hello,
two weeks ago I submitted the second version of the patch PR105387 for the bug 105387. Now I added a pointer-to-member exception test just to make sure that it doesn't break in case RTTI is enabled. The test is disabled if RTTI is disabled. I didn't receive any feedback so far regarding the second version of the patch. Is there any issue preventing acceptance?
I ran the conformance tests on libstdc++v3 by running
make -j 18 check RUNTESTFLAGS=conformance.exp
Results for the current version (only difference is the added pointer-to-member test):
Without RTTI before applying patch:
=== libstdc++ Summary ===
# of expected passes 14560
# of unexpected failures 5
# of expected failures 95
# of unsupported tests 702
Without RTTI after applying patch:
=== libstdc++ Summary ===
# of expected passes 14562
# of unexpected failures 5
# of expected failures 95
# of unsupported tests 703
With RTTI before applying patch:
=== libstdc++ Summary ===
# of expected passes 14598
# of unexpected failures 2
# of expected failures 95
# of unsupported tests 683
With RTTI after applying patch:
=== libstdc++ Summary ===
# of expected passes 14602
# of unexpected failures 2
# of expected failures 95
# of unsupported tests 683
Given that the pointer-to-member test is disabled when RTTI is disabled, the results look logical to me.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-PATCH-libstdc-fix-pointer-type-exception-catch-no-RT.patch --]
[-- Type: text/x-patch; name="0001-PATCH-libstdc-fix-pointer-type-exception-catch-no-RT.patch", Size: 5728 bytes --]
From 26004c6f26f4b2f3e664184767d861c7291f3a16 Mon Sep 17 00:00:00 2001
From: Jakob Hasse <0xjakob@users.noreply.github.com>
Date: Tue, 26 Apr 2022 12:03:47 +0800
Subject: [PATCH] [PATCH] libstdc++: fix pointer type exception catch (no RTTI)
[PR105387]
PR libstdc++/105387
__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:
* libsupc++/pbase_type_info.cc (__do_catch):
* testsuite/18_support/105387.cc: New test.
Signed-off-by: Jakob Hasse <jakob.hasse@espressif.com>
---
libstdc++-v3/libsupc++/pbase_type_info.cc | 7 ++-
libstdc++-v3/testsuite/18_support/105387.cc | 61 +++++++++++++++++++
.../18_support/exception_ptr/ptr_to_member.cc | 25 ++++++++
3 files changed, 92 insertions(+), 1 deletion(-)
create mode 100644 libstdc++-v3/testsuite/18_support/105387.cc
create mode 100644 libstdc++-v3/testsuite/18_support/exception_ptr/ptr_to_member.cc
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..5cec222c334
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/105387.cc
@@ -0,0 +1,61 @@
+#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, nullptr, 1) == false);
+}
+
+int main()
+{
+ portable_test();
+ non_portable_test();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/ptr_to_member.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/ptr_to_member.cc
new file mode 100644
index 00000000000..dbe2dafebf0
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/ptr_to_member.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;
+}
--
2.25.1
next reply other threads:[~2022-05-25 2:29 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-25 2:29 Jakob Hasse [this message]
2022-05-25 15:18 ` Jonathan Wakely
2022-10-11 15:04 ` Jakob Hasse
2022-11-05 14:01 ` Jonathan Wakely
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=HK0PR04MB253054AE1AD1416F3C9DE016E4D69@HK0PR04MB2530.apcprd04.prod.outlook.com \
--to=jakob.hasse@espressif.com \
--cc=anton.maklakov@espressif.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=ivan@espressif.com \
--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).