address sanitizer reports error when statically casting an invalid pointer
14,709
Shouldn't the pointer offset and therefore the correct resulting pointer value be known at compile time?
No, offset of virtually inherited class is not known at compile-time so compiler calculates it at runtime by accessing vtable.
Here's a simple example:
Base *foo(Derived *p) {
return static_cast<Base*>(p);
}
It compiles to
movq (%rdi), %rax # Get vptr
addq -24(%rax), %rdi # Load offset of Base from vtable
movq %rdi, %rax # Return result
ret
ASan complains because you try to access some random memory address which causes a segfault.
Related videos on Youtube
Author by
nyronium
Updated on June 04, 2022Comments
-
nyronium almost 2 years
When statically casting a
Derived*
in unallocated memory to aBase*
, gcc's ASAN reports:ASAN:DEADLYSIGNAL ================================================================= ==12829==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x563da3783776 bp 0x7ffde1670e50 sp 0x7ffde166d800 T0) ==12829==The signal is caused by a READ memory access. ==12829==Hint: address points to the zero page.
For the test I used this setup:
struct Base2 { int dummy; }; struct Base { int dummy2; }; struct Derived : public Base2, public virtual Base { }; Derived* derived = (Derived*)0x1122334455667788; /* some pointer into non-allocated memory */ Base* base = static_cast<Base*>(derived); /* ASAN fails here */
Why does ASAN report an invalid read access here? Shouldn't the pointer offset and therefore the correct resulting pointer value be known at compile time?
So why is this read access even necessary?
-
UKMonkey about 6 yearsFirstly,
0x1122334455667788
isn't what you think it is... It's more than likely truncated to0x55667788
because it's taken as a conversion from an int. Secondly, thevirtual
isn't needed since you don't inheritBase
multiple times. Finally, your error is about a null pointer access which you don't do in your snipit - so I don't think anyone can give you a reply that's meaningful -
yugr about 6 years@UKMonkey "which you don't do in your snipit" - he does, casting to virtually inherited class requires vtable access.
-
UKMonkey about 6 years@yugr and with no virtual functions, there is no vtable; which gives the null ptr access.... so infact the virtual inheritance is the cause of the problem. Interesting. (I try to avoid Diamond of Death situations; so my understanding of the impact of the virtual inheritance is a little fuzzy) Sounds like you've a nice answer there :)
-
yugr about 6 years@UKMonkey I think you still need vtable if there are virtual base classes (even if no virtual functions) because compiler does not know their offsets until runtime. See my answer below for code which GCC 4.8 generates.
-