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

Reply via email to