ubsan_handlers_cxx.cc revision 303975
119304Speter//===-- ubsan_handlers_cxx.cc ---------------------------------------------===// 219304Speter// 319304Speter// The LLVM Compiler Infrastructure 419304Speter// 519304Speter// This file is distributed under the University of Illinois Open Source 619304Speter// License. See LICENSE.TXT for details. 719304Speter// 819304Speter//===----------------------------------------------------------------------===// 919304Speter// 1019304Speter// Error logging entry points for the UBSan runtime, which are only used for C++ 1119304Speter// compilations. This file is permitted to use language features which require 1219304Speter// linking against a C++ ABI library. 13254225Speter// 1419304Speter//===----------------------------------------------------------------------===// 1519304Speter 1619304Speter#include "ubsan_platform.h" 1719304Speter#if CAN_SANITIZE_UB 1819304Speter#include "ubsan_handlers_cxx.h" 1919304Speter#include "ubsan_diag.h" 2019304Speter#include "ubsan_type_hash.h" 2119304Speter 2219304Speter#include "sanitizer_common/sanitizer_common.h" 2319304Speter#include "sanitizer_common/sanitizer_suppressions.h" 2419304Speter 2519304Speterusing namespace __sanitizer; 2619304Speterusing namespace __ubsan; 2719304Speter 2819304Speternamespace __ubsan { 2919304Speter extern const char *TypeCheckKinds[]; 3019304Speter} 3119304Speter 3219304Speter// Returns true if UBSan has printed an error report. 3319304Speterstatic bool HandleDynamicTypeCacheMiss( 3419304Speter DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash, 3519304Speter ReportOptions Opts) { 3619304Speter if (checkDynamicType((void*)Pointer, Data->TypeInfo, Hash)) 3719304Speter // Just a cache miss. The type matches after all. 38254225Speter return false; 3919304Speter 4019304Speter // Check if error report should be suppressed. 4119304Speter DynamicTypeInfo DTI = getDynamicTypeInfoFromObject((void*)Pointer); 4219304Speter if (DTI.isValid() && IsVptrCheckSuppressed(DTI.getMostDerivedTypeName())) 4319304Speter return false; 4419304Speter 4519304Speter SourceLocation Loc = Data->Loc.acquire(); 4619304Speter ErrorType ET = ErrorType::DynamicTypeMismatch; 4719304Speter if (ignoreReport(Loc, Opts, ET)) 4819304Speter return false; 4919304Speter 5019304Speter ScopedReport R(Opts, Loc, ET); 5119304Speter 5219304Speter Diag(Loc, DL_Error, 5319304Speter "%0 address %1 which does not point to an object of type %2") 5419304Speter << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type; 5519304Speter 5619304Speter // If possible, say what type it actually points to. 5719304Speter if (!DTI.isValid()) 5819304Speter Diag(Pointer, DL_Note, "object has invalid vptr") 5919304Speter << TypeName(DTI.getMostDerivedTypeName()) 6019304Speter << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr"); 61254225Speter else if (!DTI.getOffset()) 6219304Speter Diag(Pointer, DL_Note, "object is of type %0") 6319304Speter << TypeName(DTI.getMostDerivedTypeName()) 6419304Speter << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0"); 6519304Speter else 6619304Speter // FIXME: Find the type at the specified offset, and include that 6719304Speter // in the note. 6819304Speter Diag(Pointer - DTI.getOffset(), DL_Note, 6919304Speter "object is base class subobject at offset %0 within object of type %1") 7019304Speter << DTI.getOffset() << TypeName(DTI.getMostDerivedTypeName()) 7119304Speter << TypeName(DTI.getSubobjectTypeName()) 7219304Speter << Range(Pointer, Pointer + sizeof(uptr), 7319304Speter "vptr for %2 base class of %1"); 7419304Speter return true; 7519304Speter} 7619304Speter 7719304Spetervoid __ubsan::__ubsan_handle_dynamic_type_cache_miss( 7819304Speter DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) { 7919304Speter GET_REPORT_OPTIONS(false); 8019304Speter HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts); 8119304Speter} 8219304Spetervoid __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort( 8319304Speter DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) { 84254225Speter // Note: -fsanitize=vptr is always recoverable. 8519304Speter GET_REPORT_OPTIONS(false); 8619304Speter if (HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts)) 8719304Speter Die(); 8819304Speter} 8919304Speter 9019304Speterstatic void HandleCFIBadType(CFIBadTypeData *Data, ValueHandle Vtable, 9119304Speter ReportOptions Opts) { 9219304Speter SourceLocation Loc = Data->Loc.acquire(); 9319304Speter ErrorType ET = ErrorType::CFIBadType; 9419304Speter 9519304Speter if (ignoreReport(Loc, Opts, ET)) 96254225Speter return; 9719304Speter 9819304Speter ScopedReport R(Opts, Loc, ET); 9919304Speter DynamicTypeInfo DTI = getDynamicTypeInfoFromVtable((void*)Vtable); 10019304Speter 10119304Speter static const char *TypeCheckKinds[] = { 10219304Speter "virtual call", 10319304Speter "non-virtual call", 10419304Speter "base-to-derived cast", 10519304Speter "cast to unrelated type", 10619304Speter }; 10719304Speter 10819304Speter Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during " 10919304Speter "%1 (vtable address %2)") 11019304Speter << Data->Type << TypeCheckKinds[Data->TypeCheckKind] << (void *)Vtable; 111254225Speter 11219304Speter // If possible, say what type it actually points to. 11319304Speter if (!DTI.isValid()) 11419304Speter Diag(Vtable, DL_Note, "invalid vtable"); 11519304Speter else 11619304Speter Diag(Vtable, DL_Note, "vtable is of type %0") 11719304Speter << TypeName(DTI.getMostDerivedTypeName()); 11819304Speter} 11919304Speter 120254225Spetervoid __ubsan::__ubsan_handle_cfi_bad_type(CFIBadTypeData *Data, 12119304Speter ValueHandle Vtable) { 12219304Speter GET_REPORT_OPTIONS(false); 123254225Speter HandleCFIBadType(Data, Vtable, Opts); 12419304Speter} 12519304Speter 12619304Spetervoid __ubsan::__ubsan_handle_cfi_bad_type_abort(CFIBadTypeData *Data, 12719304Speter ValueHandle Vtable) { 12819304Speter GET_REPORT_OPTIONS(true); 12919304Speter HandleCFIBadType(Data, Vtable, Opts); 13019304Speter Die(); 13119304Speter} 13219304Speter 13319304Speter#endif // CAN_SANITIZE_UB 13419304Speter