UBSan false positive (?) with virtual inheritance

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.

ubsan.cpp (265 Bytes)

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.

… 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.

Thank you a lot, Richard!

01.02.2020 06:09, Richard Smith пишет: