Recently, I ended up wasting a bit of time behind a UBSan failure inside Clang:
external/llvm-project/clang/include/clang/AST/Redeclarable.h:200:15: runtime error: downcast of address 0x000120e16908 which does not point to an object of type 'clang::TranslationUnitDecl'
0x000120e16908: note: object is of type 'clang::Decl'
00 00 00 00 30 b7 ff 0d 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
^~~~~~~~~~~~~~~~~~~~~~~
vptr for 'clang::Decl'
#0 0x10533ad48 in clang::Redeclarable<clang::TranslationUnitDecl>::Redeclarable(clang::ASTContext const&)+0xf8 (scip-clang:arm64+0x104f02d48)
#1 0x10533a8d0 in clang::TranslationUnitDecl::TranslationUnitDecl(clang::ASTContext&)+0x13c (scip-clang:arm64+0x104f028d0)
#2 0x10533ad88 in clang::TranslationUnitDecl::TranslationUnitDecl(clang::ASTContext&)+0x20 (scip-clang:arm64+0x104f02d88)
#3 0x105388068 in clang::TranslationUnitDecl::Create(clang::ASTContext&)+0x3c (scip-clang:arm64+0x104f50068)
Turns out, it was “user error”, the default build has turned off the vptr check since when the LLVM_USE_SANITIZER=Undefined option was introduced over 8 years ago. Introduce -DLLVM_USE_SANITIZER=Undefined CMake option to build UBSan-… · llvm/llvm-project@4ee2675 · GitHub
Based on a cursory look at the code, it seems like the problem is coming up because operator new
is coming from the parent class Decl
, and LLVM’s custom RTTI system knows that this
points to a TranslationUnitDecl
, but UBSan is presumably unaware of that, so the dynamic type check it introduces for the static_cast
in Redeclarable.h
fails.
Is that the right assessment of the problem? If so, is turning off the check necessary because of LLVM’s custom RTTI system, or is there a way to inform UBSan to perform the checks differently?
Relatedly, does anyone know why the function
check is disabled too? It was turned off in this commit ([CMake] Add -fno-sanitize=function to UBSan bootstrap · llvm/llvm-project@ead5b93 · GitHub) without any explanation.