This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Zero vptr in dtor for -fsanitize=vptr.


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]