This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Zero vptr in dtor for -fsanitize=vptr.
- From: Martin Liška <mliska at suse dot cz>
- To: Jakub Jelinek <jakub at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org, Jason Merrill <jason at redhat dot com>
- Date: Fri, 27 Oct 2017 13:16:08 +0200
- Subject: Re: [PATCH] Zero vptr in dtor for -fsanitize=vptr.
- Authentication-results: sourceware.org; auth=none
- References: <1d468e04-9f25-65f4-04a1-51b35abb3582@suse.cz> <20171027105212.GC14653@tucnak>
On 10/27/2017 12:52 PM, Jakub Jelinek wrote:
The decl.c change seems to be only incremental change from a not publicly
posted patch rather than the full diff against trunk.
Sorry for that. Sending full patch.
Martin
>From df0cc0c2da18b150b1f0fbef418450a223470d7f Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Thu, 19 Oct 2017 11:10:19 +0200
Subject: [PATCH] Zero vptr in dtor for -fsanitize=vptr.
gcc/cp/ChangeLog:
2017-10-27 Martin Liska <mliska@suse.cz>
* decl.c (begin_destructor_body): In case of disabled recovery,
we can zero object in order to catch virtual calls after
an object lifetime.
gcc/testsuite/ChangeLog:
2017-10-27 Martin Liska <mliska@suse.cz>
* g++.dg/ubsan/vptr-12.C: New test.
---
gcc/cp/decl.c | 14 +++++++++++++-
gcc/testsuite/g++.dg/ubsan/vptr-12.C | 26 ++++++++++++++++++++++++++
2 files changed, 39 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/ubsan/vptr-12.C
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 42b52748e2a..69636e30008 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -15280,7 +15280,19 @@ begin_destructor_body (void)
if (flag_lifetime_dse
/* Clobbering an empty base is harmful if it overlays real data. */
&& !is_empty_class (current_class_type))
- finish_decl_cleanup (NULL_TREE, build_clobber_this ());
+ {
+ if (sanitize_flags_p (SANITIZE_VPTR)
+ && (flag_sanitize_recover & SANITIZE_VPTR) == 0)
+ {
+ tree fndecl = builtin_decl_explicit (BUILT_IN_MEMSET);
+ tree call = build_call_expr (fndecl, 3,
+ current_class_ptr, integer_zero_node,
+ TYPE_SIZE_UNIT (current_class_type));
+ finish_decl_cleanup (NULL_TREE, call);
+ }
+ else
+ finish_decl_cleanup (NULL_TREE, build_clobber_this ());
+ }
/* And insert cleanups for our bases and members so that they
will be properly destroyed if we throw. */
diff --git a/gcc/testsuite/g++.dg/ubsan/vptr-12.C b/gcc/testsuite/g++.dg/ubsan/vptr-12.C
new file mode 100644
index 00000000000..96c8473d757
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/vptr-12.C
@@ -0,0 +1,26 @@
+// { dg-do run }
+// { dg-shouldfail "ubsan" }
+// { dg-options "-fsanitize=vptr -fno-sanitize-recover=vptr" }
+
+struct MyClass
+{
+ virtual ~MyClass () {}
+ virtual void
+ Doit ()
+ {
+ }
+};
+
+int
+main ()
+{
+ MyClass *c = new MyClass;
+ c->~MyClass ();
+ c->Doit ();
+
+ return 0;
+}
+
+// { dg-output "\[^\n\r]*vptr-12.C:19:\[0-9]*: runtime error: member call on address 0x\[0-9a-fA-F]* which does not point to an object of type 'MyClass'(\n|\r\n|\r)" }
+// { dg-output "0x\[0-9a-fA-F]*: note: object has invalid vptr(\n|\r\n|\r)" }
+
--
2.14.2