On Fri, Oct 27, 2017 at 01:16:08PM +0200, Martin Liška wrote:
> 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.

Thanks.

> --- 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));

I wonder if it wouldn't be cheaper to just use thisref = {}; rather than
memset, pretty much the same thing as build_clobber_this () emits, except
for the TREE_VOLATILE.  Also, build_clobber_this has:
  if (vbases)
    exprstmt = build_if_in_charge (exprstmt);
so it doesn't clobber if not in charge, not sure if it applies here too.
So maybe easiest would be add a bool argument to build_clobber_this which
would say whether it is a clobber or real clearing?

> +           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 ()
> +  {
> +  }

Why not put all the above 4 lines into a single one, the dtor already uses
that kind of formatting.

> +};
> +
> +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)" }
> +

Unnecessary empty line at end.

        Jakub

Reply via email to