[Bug c++/95221] g++.dg/ubsan/vptr-12.C fails with -fstrong-eval-order=all

2020-06-01 Thread cvs-commit at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95221

--- Comment #9 from CVS Commits  ---
The master branch has been updated by Jason Merrill :

https://gcc.gnu.org/g:172f2c42a10fd470c93f1e84575de9766c157591

commit r11-775-g172f2c42a10fd470c93f1e84575de9766c157591
Author: Jason Merrill 
Date:   Mon Jun 1 16:20:38 2020 -0400

c++: vptr ubsan and object of known type [PR95466]

Another case where we can't find the OBJ_TYPE_REF_OBJECT in the
OBJ_TYPE_REF_EXPR.  So let's just evaluate the sanitize call first.

gcc/cp/ChangeLog:

PR c++/95466
PR c++/95311
PR c++/95221
* class.c (build_vfn_ref): Revert 95311 change.
* cp-ubsan.c (cp_ubsan_maybe_instrument_member_call): Build a
COMPOUND_EXPR.

gcc/testsuite/ChangeLog:

PR c++/95466
* g++.dg/ubsan/vptr-17.C: New test.

[Bug c++/95221] g++.dg/ubsan/vptr-12.C fails with -fstrong-eval-order=all

2020-05-29 Thread cvs-commit at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95221

--- Comment #8 from CVS Commits  ---
The master branch has been updated by Jason Merrill :

https://gcc.gnu.org/g:8e915901deb3518d4bef73ea52eab2ece7a2bbf6

commit r11-728-g8e915901deb3518d4bef73ea52eab2ece7a2bbf6
Author: Jason Merrill 
Date:   Fri May 29 11:59:33 2020 -0400

c++: vptr ubsan and derived class [PR95311].

We weren't able to find OBJ_TYPE_REF_OBJECT walking through
OBJ_TYPE_REF_EXPR because we had folded away the ADDR_EXPR.

gcc/cp/ChangeLog:

PR c++/95311
PR c++/95221
* class.c (build_vfn_ref): Don't fold the INDIRECT_REF.

gcc/testsuite/ChangeLog:

PR c++/95311
* g++.dg/ubsan/vptr-16.C: New test.

[Bug c++/95221] g++.dg/ubsan/vptr-12.C fails with -fstrong-eval-order=all

2020-05-22 Thread jason at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95221

Jason Merrill  changed:

   What|Removed |Added

   Target Milestone|--- |11.0
 Status|ASSIGNED|RESOLVED
 Resolution|--- |FIXED

--- Comment #7 from Jason Merrill  ---
Fixed.

[Bug c++/95221] g++.dg/ubsan/vptr-12.C fails with -fstrong-eval-order=all

2020-05-21 Thread jason at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95221

Jason Merrill  changed:

   What|Removed |Added

   Assignee|unassigned at gcc dot gnu.org  |jason at gcc dot gnu.org
 Status|NEW |ASSIGNED

[Bug c++/95221] g++.dg/ubsan/vptr-12.C fails with -fstrong-eval-order=all

2020-05-19 Thread jason at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95221

Jason Merrill  changed:

   What|Removed |Added

 Ever confirmed|0   |1
   Last reconfirmed||2020-05-20
 Status|UNCONFIRMED |NEW

--- Comment #6 from Jason Merrill  ---
(In reply to Marek Polacek from comment #2)
> I think the thing is that we have a CALL_EXPR, something like
> 
>   OBJ_TYPE_REF (...) (.UBSAN_VPTR ())
> 
> and now we first evaluate the OBJ_TYPE_REF.

Yep, that's the problem.

We're currently sanitizing the vtable when determining the 'this' argument to
the function, separately from looking at the vtable in order to determine which
function to call.  In C++14 we evaluate 'this' first, in C++17 we evaluate the
function first.  build_over_call tries to share any side-effects between the
'this' and the OBJ_TYPE_REF with a save_expr, but then
cp_ubsan_maybe_instrument_member_call adds the sanitization only to the 'this'
argument, breaking that sharing and introducing a fragile order dependency.

A simple fix might be to not preevaluate when CALL_EXPR_FN is an OBJ_TYPE_REF,
as the sharing above should mean that side-effects happen when the object
argument is evaluated, which should be what we want.  It occurs to me that the
current preevaluation is wrong for a virtual assignment when
CALL_EXPR_REVERSE_ARGS is set.

[Bug c++/95221] g++.dg/ubsan/vptr-12.C fails with -fstrong-eval-order=all

2020-05-19 Thread mpolacek at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95221

--- Comment #5 from Marek Polacek  ---
You're not wrong, but here we're dealing with the undefined behavior sanitizer
whose point is to detect broken code like the above.

[Bug c++/95221] g++.dg/ubsan/vptr-12.C fails with -fstrong-eval-order=all

2020-05-19 Thread pinskia at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95221

--- Comment #4 from Andrew Pinski  ---
Is this code even defined?
We call a method after calling the deconstructor on the object?
If we do:
 c->~MyClass ();
 new(c) MyClass();
 c->Doit ();

Then it is defined.

Or am I wrong about that?

[Bug c++/95221] g++.dg/ubsan/vptr-12.C fails with -fstrong-eval-order=all

2020-05-19 Thread mpolacek at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95221

--- Comment #3 from Marek Polacek  ---
And for completeness, the asm for the -fstrong-eval-order=all case:

movq%rbx, %rdi
call*%r12
movq-24(%rbp), %rax
movq(%rax), %rax
addq$16, %rax
movq(%rax), %r12 # crash here

Any ideas what as to we want to do here?

[Bug c++/95221] g++.dg/ubsan/vptr-12.C fails with -fstrong-eval-order=all

2020-05-19 Thread mpolacek at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95221

--- Comment #2 from Marek Polacek  ---
I think the thing is that we have a CALL_EXPR, something like

  OBJ_TYPE_REF (...) (.UBSAN_VPTR ())

and now we first evaluate the OBJ_TYPE_REF.  In this case this is what seems to
happen here:

1) we evaluate OBJ_TYPE_REF before the arguments:

 OBJ_TYPE_REF(_2;(struct MyClass)c->0) (c.0);

   I think this calls the destructor of 'c', and that clears up the vptr:

 this->_vptr.MyClass = 0B;

2) then we fetch the vptr:

  _5 = c->_vptr.MyClass; // _5 == null

3) we add the offset to the vtable for Doit:

  _6 = _5 + 16;  // _6 == 16

4) we deref the pointer and crash

  _7 = *_6;


With -fstrong-eval-order=some we instead do this

_3 = c->_vptr.MyClass;
_4 = *_3;
OBJ_TYPE_REF(_4;(struct MyClass)c->0) (c.0);

so there's no crash, and the subsequent call to the ubsan routine:

_5 = c.1->_vptr.MyClass;
_6 = (long unsigned int) _5; 
.UBSAN_VPTR (c.1, _6, 2968783897514143607, &_ZTI7MyClass, 4B);

reports the error, because it sees that _6 is null.

[Bug c++/95221] g++.dg/ubsan/vptr-12.C fails with -fstrong-eval-order=all

2020-05-19 Thread mpolacek at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95221

--- Comment #1 from Marek Polacek  ---
It is caused by this code:

 853   if (flag_strong_eval_order == 2
 854   && CALL_EXPR_FN (*expr_p)
 855   && cp_get_callee_fndecl_nofold (*expr_p) == NULL_TREE)
 856 {
 857   tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
 858   enum gimplify_status t
 859 = gimplify_to_rvalue (_EXPR_FN (*expr_p), pre_p, NULL,
 860   is_gimple_call_addr);
 861   if (t == GS_ERROR)
 862 ret = GS_ERROR;
 863   /* GIMPLE considers most pointer conversion useless, but for
 864  calls we actually care about the exact function pointer type.
 */
 865   else if (TREE_TYPE (CALL_EXPR_FN (*expr_p)) != fnptrtype)
 866 CALL_EXPR_FN (*expr_p)
 867   = build1 (NOP_EXPR, fnptrtype, CALL_EXPR_FN (*expr_p));
 868 }

and causes this difference:

--- 1g  2020-05-19 11:42:32.123168379 -0400
+++ 2g  2020-05-19 11:42:41.254133594 -0400
@@ -18,21 +18,21 @@
 operator delete (D.2725, 8);
   }
 c = D.2725;
+_1 = c->_vptr.MyClass;
+_2 = *_1;
 c.0 = c;
-_1 = c.0->_vptr.MyClass;
-_2 = (long unsigned int) _1;
-.UBSAN_VPTR (c.0, _2, 2968783897514143607, &_ZTI7MyClass, 4B);
-_3 = c->_vptr.MyClass;
-_4 = *_3;
-OBJ_TYPE_REF(_4;(struct MyClass)c->0) (c.0);
+_3 = c.0->_vptr.MyClass;
+_4 = (long unsigned int) _3;
+.UBSAN_VPTR (c.0, _4, 2968783897514143607, &_ZTI7MyClass, 4B);
+OBJ_TYPE_REF(_2;(struct MyClass)c->0) (c.0);
+_5 = c->_vptr.MyClass;
+_6 = _5 + 16;
+_7 = *_6;
 c.1 = c;
-_5 = c.1->_vptr.MyClass;
-_6 = (long unsigned int) _5;
-.UBSAN_VPTR (c.1, _6, 2968783897514143607, &_ZTI7MyClass, 4B);
-_7 = c->_vptr.MyClass;
-_8 = _7 + 16;
-_9 = *_8;
-OBJ_TYPE_REF(_9;(struct MyClass)c->2) (c.1);
+_8 = c.1->_vptr.MyClass;
+_9 = (long unsigned int) _8;
+.UBSAN_VPTR (c.1, _9, 2968783897514143607, &_ZTI7MyClass, 4B);
+OBJ_TYPE_REF(_7;(struct MyClass)c->2) (c.1);
 D.2751 = 0;
 return D.2751;
   }