UBSan false positive (?) with virtual inheritance

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

UBSan false positive (?) with virtual inheritance

Hans Wennborg via cfe-dev

Hello everyone,

The code example below triggers an undefined behavior sanitizer warning when compiled with -O1 and higher:

     1  struct Aux {
     2    virtual ~Aux() = default;
     3    int i = 0;
     4  };
     5
     6  struct Base {
     7    virtual ~Base() = default;
     8  };
     9
    10  struct A : public virtual Base, public Aux {};
    11
    12  struct B final : public virtual A {};
    13
    14  void check(const A &a) {}
    15
    16  int main() {
    17    B b;
    18    check(b); // UBSan warns here
    19    return 0;
    20  }

When compiled with -fsanitize=undefined:

example.cpp:18:9: runtime error: reference binding to address 0x7ffe652149c8 with insufficient space for an object of type 'const A'

When compiled with -fsanitize=object-size:

example.cpp:12:8: runtime error: constructor call on address 0x7ffc7988a2e0 with insufficient space for an object of type 'A'

example.cpp:18:9: runtime error: reference binding to address 0x7ffc7988a2e0 with insufficient space for an object of type 'const A'

Could someone tell if it is a sanitizer false positive or does this case actually contains a kind of UB? GCC doesn't give any warning for this code.



_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

ubsan.cpp (285 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: UBSan false positive (?) with virtual inheritance

Hans Wennborg via cfe-dev
This looks like a bug to me; it looks like we're checking for the size of an A being available, but should only be checking for the nvsize since we don't know we have an object whose most-derived type is A.

On Thu, 30 Jan 2020, 23:45 Alexey Sidorin via cfe-dev, <[hidden email]> wrote:

Hello everyone,

The code example below triggers an undefined behavior sanitizer warning when compiled with -O1 and higher:

     1  struct Aux {
     2    virtual ~Aux() = default;
     3    int i = 0;
     4  };
     5
     6  struct Base {
     7    virtual ~Base() = default;
     8  };
     9
    10  struct A : public virtual Base, public Aux {};
    11
    12  struct B final : public virtual A {};
    13
    14  void check(const A &a) {}
    15
    16  int main() {
    17    B b;
    18    check(b); // UBSan warns here
    19    return 0;
    20  }

When compiled with -fsanitize=undefined:

example.cpp:18:9: runtime error: reference binding to address 0x7ffe652149c8 with insufficient space for an object of type 'const A'

When compiled with -fsanitize=object-size:

example.cpp:12:8: runtime error: constructor call on address 0x7ffc7988a2e0 with insufficient space for an object of type 'A'

example.cpp:18:9: runtime error: reference binding to address 0x7ffc7988a2e0 with insufficient space for an object of type 'const A'

Could someone tell if it is a sanitizer false positive or does this case actually contains a kind of UB? GCC doesn't give any warning for this code.


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: UBSan false positive (?) with virtual inheritance

Hans Wennborg via cfe-dev
... and in fact we also generate wrong code for this example with the sanitizers disabled -- we mark the reference parameter as dereferenceable(sizeof(A)) rather than dereferenceable(nvsize(A)). Oops!

Fixed in master.

On Fri, 31 Jan 2020 at 09:54, Richard Smith <[hidden email]> wrote:
This looks like a bug to me; it looks like we're checking for the size of an A being available, but should only be checking for the nvsize since we don't know we have an object whose most-derived type is A.

On Thu, 30 Jan 2020, 23:45 Alexey Sidorin via cfe-dev, <[hidden email]> wrote:

Hello everyone,

The code example below triggers an undefined behavior sanitizer warning when compiled with -O1 and higher:

     1  struct Aux {
     2    virtual ~Aux() = default;
     3    int i = 0;
     4  };
     5
     6  struct Base {
     7    virtual ~Base() = default;
     8  };
     9
    10  struct A : public virtual Base, public Aux {};
    11
    12  struct B final : public virtual A {};
    13
    14  void check(const A &a) {}
    15
    16  int main() {
    17    B b;
    18    check(b); // UBSan warns here
    19    return 0;
    20  }

When compiled with -fsanitize=undefined:

example.cpp:18:9: runtime error: reference binding to address 0x7ffe652149c8 with insufficient space for an object of type 'const A'

When compiled with -fsanitize=object-size:

example.cpp:12:8: runtime error: constructor call on address 0x7ffc7988a2e0 with insufficient space for an object of type 'A'

example.cpp:18:9: runtime error: reference binding to address 0x7ffc7988a2e0 with insufficient space for an object of type 'const A'

Could someone tell if it is a sanitizer false positive or does this case actually contains a kind of UB? GCC doesn't give any warning for this code.


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: UBSan false positive (?) with virtual inheritance

Hans Wennborg via cfe-dev
Thank you a lot, Richard!


01.02.2020 06:09, Richard Smith пишет:
... and in fact we also generate wrong code for this example with the sanitizers disabled -- we mark the reference parameter as dereferenceable(sizeof(A)) rather than dereferenceable(nvsize(A)). Oops!

Fixed in master.

On Fri, 31 Jan 2020 at 09:54, Richard Smith <[hidden email]> wrote:
This looks like a bug to me; it looks like we're checking for the size of an A being available, but should only be checking for the nvsize since we don't know we have an object whose most-derived type is A.

On Thu, 30 Jan 2020, 23:45 Alexey Sidorin via cfe-dev, <[hidden email]> wrote:

Hello everyone,

The code example below triggers an undefined behavior sanitizer warning when compiled with -O1 and higher:

     1  struct Aux {
     2    virtual ~Aux() = default;
     3    int i = 0;
     4  };
     5
     6  struct Base {
     7    virtual ~Base() = default;
     8  };
     9
    10  struct A : public virtual Base, public Aux {};
    11
    12  struct B final : public virtual A {};
    13
    14  void check(const A &a) {}
    15
    16  int main() {
    17    B b;
    18    check(b); // UBSan warns here
    19    return 0;
    20  }

When compiled with -fsanitize=undefined:

example.cpp:18:9: runtime error: reference binding to address 0x7ffe652149c8 with insufficient space for an object of type 'const A'

When compiled with -fsanitize=object-size:

example.cpp:12:8: runtime error: constructor call on address 0x7ffc7988a2e0 with insufficient space for an object of type 'A'

example.cpp:18:9: runtime error: reference binding to address 0x7ffc7988a2e0 with insufficient space for an object of type 'const A'

Could someone tell if it is a sanitizer false positive or does this case actually contains a kind of UB? GCC doesn't give any warning for this code.


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev