https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117976

            Bug ID: 117976
           Summary: ubsan false positive invoking pointer to derived
                    member with base class type
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: sanitizer
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rs2740 at gmail dot com
                CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
                    jakub at gcc dot gnu.org, kcc at gcc dot gnu.org
  Target Milestone: ---

struct B1 {
    virtual ~B1() = default;
    int x;
};

struct B2 {
    virtual ~B2() = default;
    int y;
};

struct D : B1, B2 {
    int x;
    void f() {}
};

int main() {
    D d;
    B2* b = &d;
    auto mptr = static_cast<void (B2::*)()>(&D::f);
    (b->*mptr)();
}

This example should be valid. [expr.static.cast]/12:

> A prvalue of type “pointer to member of D of type cv1 T” can be converted to a
> prvalue of type “pointer to member of B of type cv2 T”, where D is a complete 
> class type and B is a base class of D, if cv2 is the same cv-qualification 
> as, 
> or greater cv-qualification than, cv1. [...] If class B contains the original 
> member, or is a base class of the class containing the original member, the 
> resulting pointer to member points to the original member. Otherwise, the 
> behavior is undefined.

> [Note 6: Although class B need not contain the original member, the dynamic
> type of the object with which indirection through the pointer to member is 
> performed must contain the original member; see [expr.mptr.oper]. — end note]

The "original member" is D::f; B2 is a base class of D, so the resulting
pointer to member points to the original member. The dynamic type of the object
is D, which does contain the original member. 

However, g++ -fsanitize=undefined && ./a.out complains:
test.cpp:20:15: runtime error: member call on address 0x7fffffff8d80 which does
not point to an object of type 'B2'
0x7fffffff8d80: note: object is of type 'D'
 ff ff ff ff  68 14 40 00 00 00 00 00  0d 14 40 00 00 00 00 00  88 14 40 00 00
00 00 00  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'D'

Using clang++ reports no errors.

PR92678 looks similar, though that one is calling through the derived type
instead of the base type.

Reply via email to