Commit 4cf6b06c by Jakub Jelinek

c++: Further fix for -fsanitize=vptr [PR94325]

For -fsanitize=vptr, we insert a NULL store into the vptr instead of just
adding a CLOBBER of this.  build_clobber_this makes the CLOBBER conditional
on in_charge (implicit) parameter whenever CLASSTYPE_VBASECLASSES, but when
adding this conditionalization to the -fsanitize=vptr code in PR87095,
I wanted it to catch some more cases when the class has CLASSTYPE_VBASECLASSES,
but the vptr is still not shared with something else, otherwise the
sanitization would be less effective.
The following testcase shows that the chosen test that CLASSTYPE_PRIMARY_BINFO
is non-NULL and has BINFO_VIRTUAL_P set wasn't sufficient,
the D class has still sizeof(D) == sizeof(void*) and thus contains just
a single vptr, but while in B::~B() this results in the vptr not being
cleared, in C::~C() this condition isn't true, as CLASSTYPE_PRIMARY_BINFO
in that case is B and is not BINFO_VIRTUAL_P, so it clears the vptr, but the
D::~D() dtor after invoking C::~C() invokes A::~A() with an already cleared
vptr, which is then reported.
The following patch is just a shot in the dark, keep looking through
CLASSTYPE_PRIMARY_BINFO until we find BINFO_VIRTUAL_P, but it works on the
existing testcase as well as this new one.

2020-04-08  Jakub Jelinek  <jakub@redhat.com>

	PR c++/94325
	* decl.c (begin_destructor_body): For CLASSTYPE_VBASECLASSES class
	dtors, if CLASSTYPE_PRIMARY_BINFO is non-NULL, but not BINFO_VIRTUAL_P,
	look at CLASSTYPE_PRIMARY_BINFO of its BINFO_TYPE if it is not
	BINFO_VIRTUAL_P, and so on.

	* g++.dg/ubsan/vptr-15.C: New test.
parent a6479aa4
2020-04-08 Jakub Jelinek <jakub@redhat.com>
PR c++/94325
* decl.c (begin_destructor_body): For CLASSTYPE_VBASECLASSES class
dtors, if CLASSTYPE_PRIMARY_BINFO is non-NULL, but not BINFO_VIRTUAL_P,
look at CLASSTYPE_PRIMARY_BINFO of its BINFO_TYPE if it is not
BINFO_VIRTUAL_P, and so on.
2020-04-08 Marek Polacek <polacek@redhat.com> 2020-04-08 Marek Polacek <polacek@redhat.com>
PR c++/94478 - ICE with defaulted comparison operator PR c++/94478 - ICE with defaulted comparison operator
......
...@@ -16663,14 +16663,20 @@ begin_destructor_body (void) ...@@ -16663,14 +16663,20 @@ begin_destructor_body (void)
/* If the vptr is shared with some virtual nearly empty base, /* If the vptr is shared with some virtual nearly empty base,
don't clear it if not in charge, the dtor of the virtual don't clear it if not in charge, the dtor of the virtual
nearly empty base will do that later. */ nearly empty base will do that later. */
if (CLASSTYPE_VBASECLASSES (current_class_type) if (CLASSTYPE_VBASECLASSES (current_class_type))
&& CLASSTYPE_PRIMARY_BINFO (current_class_type)
&& BINFO_VIRTUAL_P
(CLASSTYPE_PRIMARY_BINFO (current_class_type)))
{ {
stmt = convert_to_void (stmt, ICV_STATEMENT, tree c = current_class_type;
tf_warning_or_error); while (CLASSTYPE_PRIMARY_BINFO (c))
stmt = build_if_in_charge (stmt); {
if (BINFO_VIRTUAL_P (CLASSTYPE_PRIMARY_BINFO (c)))
{
stmt = convert_to_void (stmt, ICV_STATEMENT,
tf_warning_or_error);
stmt = build_if_in_charge (stmt);
break;
}
c = BINFO_TYPE (CLASSTYPE_PRIMARY_BINFO (c));
}
} }
finish_decl_cleanup (NULL_TREE, stmt); finish_decl_cleanup (NULL_TREE, stmt);
} }
......
2020-04-08 Jakub Jelinek <jakub@redhat.com>
PR c++/94325
* g++.dg/ubsan/vptr-15.C: New test.
2020-04-08 Marek Polacek <polacek@redhat.com> 2020-04-08 Marek Polacek <polacek@redhat.com>
PR c++/94478 - ICE with defaulted comparison operator PR c++/94478 - ICE with defaulted comparison operator
......
// PR c++/94325
// { dg-do run { target c++11 } }
// { dg-options "-fsanitize=vptr -fno-sanitize-recover=vptr" }
struct A { virtual ~A () = default; };
struct B : public virtual A {};
struct C : public B {};
struct D : public C {};
int
main ()
{
D a;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment