On Fri, Nov 03, 2017 at 03:25:25PM +0100, Martin Liška wrote: > On 10/27/2017 09:44 PM, Nathan Sidwell wrote: > > On 10/27/2017 02:34 PM, Jakub Jelinek wrote: > > > >> But when singly inheriting a polymorphic base and thus mapped to the same > >> vptr all but the last dtor will not be in charge, right? > > > > Correct. > > > >> So, if using build_clobber_this for this, instead of clobbering what we > >> clobber we'd just clear the single vptr (couldn't clobber the rest, even > >> if before the store, because that would make the earlier other vptr stores > >> dead). > > > > ok (I'd not looked at the patch to see if in chargeness was signficant) > > > > nathan > > > > Hello. > > I'm sending v2 which only zeros vptr of object. > > Ready to be installed after finishing tests? > Martin
> From 098932be5472656c834b402038accb0b861afcc1 Mon Sep 17 00:00:00 2001 > From: marxin <mli...@suse.cz> > Date: Thu, 19 Oct 2017 11:10:19 +0200 > Subject: [PATCH] Zero vptr in dtor for -fsanitize=vptr. > > gcc/cp/ChangeLog: > > 2017-11-03 Martin Liska <mli...@suse.cz> > > * decl.c (begin_destructor_body): In case of VPTR sanitization > (with disabled recovery), zero vptr in order to catch virtual calls > after lifetime of an object. > > gcc/testsuite/ChangeLog: > > 2017-10-27 Martin Liska <mli...@suse.cz> > > * g++.dg/ubsan/vptr-12.C: New test. > --- > gcc/cp/decl.c | 20 +++++++++++++++++++- > gcc/testsuite/g++.dg/ubsan/vptr-12.C | 22 ++++++++++++++++++++++ > 2 files changed, 41 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 d88c78f348b..d45cc29e636 100644 > --- a/gcc/cp/decl.c > +++ b/gcc/cp/decl.c > @@ -15241,7 +15241,25 @@ 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 binfo = TYPE_BINFO (current_class_type); > + tree ref > + = cp_build_indirect_ref (current_class_ptr, RO_NULL, > + tf_warning_or_error); > + > + tree vtbl_ptr = build_vfield_ref (ref, TREE_TYPE (binfo)); > + tree vtbl = build_zero_cst (TREE_TYPE (vtbl_ptr)); > + tree stmt = cp_build_modify_expr (input_location, vtbl_ptr, > + NOP_EXPR, vtbl, > + tf_warning_or_error); > + finish_decl_cleanup (NULL_TREE, stmt); > + } > + 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..be5c074dfc1 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/ubsan/vptr-12.C > @@ -0,0 +1,22 @@ > +// { 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:16:\[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)" } I think the last dg-output shouldn't have any regexps at the end, so: // { dg-output "0x\[0-9a-fA-F]*: note: object has invalid vptr" } Marek