1eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith//===-- ubsan_handlers_cxx.cc ---------------------------------------------===// 2eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith// 3eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith// The LLVM Compiler Infrastructure 4eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith// 5eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith// This file is distributed under the University of Illinois Open Source 6eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith// License. See LICENSE.TXT for details. 7eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith// 8eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith//===----------------------------------------------------------------------===// 9eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith// 10eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith// Error logging entry points for the UBSan runtime, which are only used for C++ 11eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith// compilations. This file is permitted to use language features which require 12eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith// linking against a C++ ABI library. 13eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith// 14eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith//===----------------------------------------------------------------------===// 15eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith 167c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include "ubsan_platform.h" 177c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#if CAN_SANITIZE_UB 18c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#include "ubsan_handlers.h" 19eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith#include "ubsan_handlers_cxx.h" 20eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith#include "ubsan_diag.h" 21eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith#include "ubsan_type_hash.h" 22eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith 23eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith#include "sanitizer_common/sanitizer_common.h" 246d1862363c88c183b0ed7740fca876342cf0474bStephen Hines#include "sanitizer_common/sanitizer_suppressions.h" 25eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith 26eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smithusing namespace __sanitizer; 27eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smithusing namespace __ubsan; 28eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith 29eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smithnamespace __ubsan { 30eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith extern const char *TypeCheckKinds[]; 31eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith} 32eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith 33799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Returns true if UBSan has printed an error report. 34799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstatic bool HandleDynamicTypeCacheMiss( 3525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash, 366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ReportOptions Opts) { 37eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith if (checkDynamicType((void*)Pointer, Data->TypeInfo, Hash)) 38eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith // Just a cache miss. The type matches after all. 39799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return false; 40eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith 416d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // Check if error report should be suppressed. 42799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar DynamicTypeInfo DTI = getDynamicTypeInfoFromObject((void*)Pointer); 4386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines if (DTI.isValid() && IsVptrCheckSuppressed(DTI.getMostDerivedTypeName())) 44799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return false; 456d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 462af552f98f980178db37eed28a609b6bf55f6df8Will Dietz SourceLocation Loc = Data->Loc.acquire(); 47799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar ErrorType ET = ErrorType::DynamicTypeMismatch; 48799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (ignoreReport(Loc, Opts, ET)) 49799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return false; 502af552f98f980178db37eed28a609b6bf55f6df8Will Dietz 51799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar ScopedReport R(Opts, Loc, ET); 526d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 532af552f98f980178db37eed28a609b6bf55f6df8Will Dietz Diag(Loc, DL_Error, 5425ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith "%0 address %1 which does not point to an object of type %2") 55eda8bd0fc07df35c9ad7de5b698bb717b063e7afRichard Smith << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type; 5625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith 5725ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith // If possible, say what type it actually points to. 58c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if (!DTI.isValid()) { 59c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if (DTI.getOffset() < -VptrMaxOffsetToTop || DTI.getOffset() > VptrMaxOffsetToTop) { 60c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Diag(Pointer, DL_Note, "object has a possibly invalid vptr: abs(offset to top) too big") 61c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar << TypeName(DTI.getMostDerivedTypeName()) 62c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar << Range(Pointer, Pointer + sizeof(uptr), "possibly invalid vptr"); 63c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar } else { 64c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Diag(Pointer, DL_Note, "object has invalid vptr") 65c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar << TypeName(DTI.getMostDerivedTypeName()) 66c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr"); 67c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar } 68c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar } else if (!DTI.getOffset()) 6925ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith Diag(Pointer, DL_Note, "object is of type %0") 70799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar << TypeName(DTI.getMostDerivedTypeName()) 716d1862363c88c183b0ed7740fca876342cf0474bStephen Hines << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0"); 7225ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith else 730ad23f7f860e27b8b9a889be665cfaea830503ceRichard Smith // FIXME: Find the type at the specified offset, and include that 740ad23f7f860e27b8b9a889be665cfaea830503ceRichard Smith // in the note. 7525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith Diag(Pointer - DTI.getOffset(), DL_Note, 7625ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith "object is base class subobject at offset %0 within object of type %1") 77799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar << DTI.getOffset() << TypeName(DTI.getMostDerivedTypeName()) 78799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar << TypeName(DTI.getSubobjectTypeName()) 796d1862363c88c183b0ed7740fca876342cf0474bStephen Hines << Range(Pointer, Pointer + sizeof(uptr), 806d1862363c88c183b0ed7740fca876342cf0474bStephen Hines "vptr for %2 base class of %1"); 81799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return true; 82a82a5d360b19080f2b1beae374c12d4f26146450Will Dietz} 83a82a5d360b19080f2b1beae374c12d4f26146450Will Dietz 84a82a5d360b19080f2b1beae374c12d4f26146450Will Dietzvoid __ubsan::__ubsan_handle_dynamic_type_cache_miss( 8525ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) { 866d1862363c88c183b0ed7740fca876342cf0474bStephen Hines GET_REPORT_OPTIONS(false); 876d1862363c88c183b0ed7740fca876342cf0474bStephen Hines HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts); 88a82a5d360b19080f2b1beae374c12d4f26146450Will Dietz} 89a82a5d360b19080f2b1beae374c12d4f26146450Will Dietzvoid __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort( 9025ee97fe8ada76755c8bd1087fac9cc3cd03b28cRichard Smith DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) { 91799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Note: -fsanitize=vptr is always recoverable. 92799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar GET_REPORT_OPTIONS(false); 93799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts)) 94799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Die(); 95799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 96799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 97c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarnamespace __ubsan { 98c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarvoid HandleCFIBadType(CFICheckFailData *Data, ValueHandle Vtable, 99c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar bool ValidVtable, ReportOptions Opts) { 100799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar SourceLocation Loc = Data->Loc.acquire(); 101799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar ErrorType ET = ErrorType::CFIBadType; 102799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 103799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (ignoreReport(Loc, Opts, ET)) 104799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return; 105799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 106799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar ScopedReport R(Opts, Loc, ET); 107c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar DynamicTypeInfo DTI = ValidVtable 108c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar ? getDynamicTypeInfoFromVtable((void *)Vtable) 109c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar : DynamicTypeInfo(0, 0, 0); 110c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 111c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar const char *CheckKindStr; 112c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar switch (Data->CheckKind) { 113c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar case CFITCK_VCall: 114c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar CheckKindStr = "virtual call"; 115c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar break; 116c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar case CFITCK_NVCall: 117c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar CheckKindStr = "non-virtual call"; 118c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar break; 119c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar case CFITCK_DerivedCast: 120c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar CheckKindStr = "base-to-derived cast"; 121c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar break; 122c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar case CFITCK_UnrelatedCast: 123c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar CheckKindStr = "cast to unrelated type"; 124c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar break; 125c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar case CFITCK_ICall: 126c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Die(); 127c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar } 128799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 129799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during " 130799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar "%1 (vtable address %2)") 131c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar << Data->Type << CheckKindStr << (void *)Vtable; 132799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 133799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // If possible, say what type it actually points to. 134c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if (!DTI.isValid()) { 135c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar const char *module = Symbolizer::GetOrInit()->GetModuleNameForPc(Vtable); 136c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if (module) 137c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Diag(Vtable, DL_Note, "invalid vtable in module %0") << module; 138c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar else 139c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar Diag(Vtable, DL_Note, "invalid vtable"); 140c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar } else { 141799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Diag(Vtable, DL_Note, "vtable is of type %0") 142799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar << TypeName(DTI.getMostDerivedTypeName()); 143c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar } 144799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 145c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar} // namespace __ubsan 146799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 147c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar#endif // CAN_SANITIZE_UB 148