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.
This commit is contained in:
Jason Merrill 2020-06-01 16:20:38 -04:00
parent 832c1192eb
commit 172f2c42a1
3 changed files with 25 additions and 15 deletions

View file

@ -729,13 +729,9 @@ build_vtbl_ref (tree instance, tree idx)
tree
build_vfn_ref (tree instance_ptr, tree idx)
{
tree obtype = TREE_TYPE (TREE_TYPE (instance_ptr));
tree aref;
/* Leave the INDIRECT_REF unfolded so cp_ubsan_maybe_instrument_member_call
can find instance_ptr. */
tree ind = build1 (INDIRECT_REF, obtype, instance_ptr);
tree aref = build_vtbl_ref (ind, idx);
aref = build_vtbl_ref (cp_build_fold_indirect_ref (instance_ptr), idx);
/* When using function descriptors, the address of the
vtable entry is treated as a function pointer. */

View file

@ -125,16 +125,11 @@ cp_ubsan_maybe_instrument_member_call (tree stmt)
{
/* Virtual function call: Sanitize the use of the object pointer in the
OBJ_TYPE_REF, since the vtable reference will SEGV otherwise (95221).
OBJ_TYPE_REF_EXPR is ptr->vptr[N] and OBJ_TYPE_REF_OBJECT is ptr. */
OBJ_TYPE_REF_EXPR is ptr->vptr[N] and OBJ_TYPE_REF_OBJECT is ptr. But
we can't be sure of finding OBJ_TYPE_REF_OBJECT in OBJ_TYPE_REF_EXPR
if the latter has been optimized, so we use a COMPOUND_EXPR below. */
opp = &OBJ_TYPE_REF_EXPR (fn);
op = OBJ_TYPE_REF_OBJECT (fn);
while (*opp != op)
{
if (TREE_CODE (*opp) == COMPOUND_EXPR)
opp = &TREE_OPERAND (*opp, 1);
else
opp = &TREE_OPERAND (*opp, 0);
}
}
else
{
@ -150,7 +145,11 @@ cp_ubsan_maybe_instrument_member_call (tree stmt)
op = cp_ubsan_maybe_instrument_vptr (EXPR_LOCATION (stmt), op,
TREE_TYPE (TREE_TYPE (op)),
true, UBSAN_MEMBER_CALL);
if (op)
if (!op)
/* No change. */;
else if (fn && TREE_CODE (fn) == OBJ_TYPE_REF)
*opp = cp_build_compound_expr (op, *opp, tf_none);
else
*opp = op;
}

View file

@ -0,0 +1,15 @@
// PR c++/95466
// { dg-additional-options -fsanitize=vptr }
class A {
virtual void m_fn1();
};
class C {
public:
virtual void m_fn2();
};
class B : A, public C {};
int main() {
B b;
static_cast<C *>(&b)->m_fn2();
}