[Bug sanitizer/94325] [8/9/10 Regression] UBSAN: "invalid vptr" false positive for virtual inheritance with -fno-sanitize-recover=all
jakub at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Mon Apr 6 11:27:53 GMT 2020
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94325
--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
sizeof (MD) == sizeof (void *), so the clearing of the vptr in DD::~DD() when
DE::~DE() is invoked later on looks wrong.
But, without -fsanitize=vptr this isn't done.
I've added that guard in PR87095, see
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87095#c3
for more details.
So, either we can just do what build_clobber_this does, which would be just:
--- gcc/cp/decl.c 2020-03-27 09:59:26.407083563 +0100
+++ gcc/cp/decl.c 2020-04-06 13:14:15.814200485 +0200
@@ -16662,10 +16662,7 @@ begin_destructor_body (void)
/* If the vptr is shared with some virtual nearly empty base,
don't clear it if not in charge, the dtor of the virtual
nearly empty base will do that later. */
- if (CLASSTYPE_VBASECLASSES (current_class_type)
- && CLASSTYPE_PRIMARY_BINFO (current_class_type)
- && BINFO_VIRTUAL_P
- (CLASSTYPE_PRIMARY_BINFO (current_class_type)))
+ if (CLASSTYPE_VBASECLASSES (current_class_type))
{
stmt = convert_to_void (stmt, ICV_STATEMENT,
tf_warning_or_error);
or try to narrow down the condition to cover this problematic case too, though
I'm afraid I have no idea what that would be.
Nathan/Jason, can I ask for help here?
A wild shot in the dark could be:
--- gcc/cp/decl.c.jj 2020-03-27 09:59:26.407083563 +0100
+++ gcc/cp/decl.c 2020-04-06 13:25:03.321511554 +0200
@@ -16662,14 +16662,20 @@ begin_destructor_body (void)
/* If the vptr is shared with some virtual nearly empty base,
don't clear it if not in charge, the dtor of the virtual
nearly empty base will do that later. */
- if (CLASSTYPE_VBASECLASSES (current_class_type)
- && CLASSTYPE_PRIMARY_BINFO (current_class_type)
- && BINFO_VIRTUAL_P
- (CLASSTYPE_PRIMARY_BINFO (current_class_type)))
+ if (CLASSTYPE_VBASECLASSES (current_class_type))
{
- stmt = convert_to_void (stmt, ICV_STATEMENT,
- tf_warning_or_error);
- stmt = build_if_in_charge (stmt);
+ tree c = current_class_type;
+ while (CLASSTYPE_PRIMARY_BINFO (c))
+ {
+ 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);
}
just from the fact that the existing code seemed to DTRT for D::~D() where
CLASSTYPE_VBASECLASSES is non-NULL, CLASSTYPE_PRIMARY_BINFO too and
BINFO_VIRTUAL_P on that is set as well.
But in DD::~DD() the last condition doesn't hold, but BINFO_TYPE of the
CLASSTYPE_PRIMARY_BINFO is D which has this property.
More information about the Gcc-bugs
mailing list