diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:45:36 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:45:36 +0000 |
commit | 6f08730ec5f639f05f2f15354171e4a3c9af9dc1 (patch) | |
tree | 7374e9d4448083010ada98d17976199c7e945d47 /lib/ubsan | |
parent | c003a57e2e4a1ad9be0338806bc1038b6987155f (diff) | |
download | src-6f08730ec5f639f05f2f15354171e4a3c9af9dc1.tar.gz src-6f08730ec5f639f05f2f15354171e4a3c9af9dc1.zip |
Vendor import of compiler-rt release_39 branch r276489:vendor/compiler-rt/compiler-rt-release_39-r276489
Notes
Notes:
svn path=/vendor/compiler-rt/dist/; revision=303235
svn path=/vendor/compiler-rt/compiler-rt-release_39-r276489/; revision=303236; tag=vendor/compiler-rt/compiler-rt-release_39-r276489
Diffstat (limited to 'lib/ubsan')
-rw-r--r-- | lib/ubsan/CMakeLists.txt | 11 | ||||
-rw-r--r-- | lib/ubsan/Makefile.mk | 28 | ||||
-rw-r--r-- | lib/ubsan/ubsan_diag.cc | 183 | ||||
-rw-r--r-- | lib/ubsan/ubsan_flags.cc | 2 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers.cc | 38 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers.h | 19 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers_cxx.cc | 80 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers_cxx.h | 14 | ||||
-rw-r--r-- | lib/ubsan/ubsan_platform.h | 3 | ||||
-rw-r--r-- | lib/ubsan/ubsan_type_hash.h | 4 | ||||
-rw-r--r-- | lib/ubsan/ubsan_type_hash_itanium.cc | 10 | ||||
-rw-r--r-- | lib/ubsan/ubsan_value.cc | 4 |
12 files changed, 210 insertions, 186 deletions
diff --git a/lib/ubsan/CMakeLists.txt b/lib/ubsan/CMakeLists.txt index 5ece9a62cfeb..901fef2bfdcf 100644 --- a/lib/ubsan/CMakeLists.txt +++ b/lib/ubsan/CMakeLists.txt @@ -22,12 +22,19 @@ set(UBSAN_CXX_SOURCES include_directories(..) set(UBSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_no_rtti_flag(UBSAN_CFLAGS) +append_rtti_flag(OFF UBSAN_CFLAGS) +append_list_if(SANITIZER_CAN_USE_CXXABI -DUBSAN_CAN_USE_CXXABI UBSAN_CFLAGS) + set(UBSAN_STANDALONE_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_no_rtti_flag(UBSAN_STANDALONE_CFLAGS) +append_rtti_flag(OFF UBSAN_STANDALONE_CFLAGS) +append_list_if(SANITIZER_CAN_USE_CXXABI -DUBSAN_CAN_USE_CXXABI UBSAN_STANDALONE_CFLAGS) + set(UBSAN_CXXFLAGS ${SANITIZER_COMMON_CFLAGS}) +append_rtti_flag(ON UBSAN_STANDALONE_CXXFLAGS) +append_list_if(SANITIZER_CAN_USE_CXXABI -DUBSAN_CAN_USE_CXXABI UBSAN_CXXFLAGS) add_custom_target(ubsan) +set_target_properties(ubsan PROPERTIES FOLDER "Compiler-RT Misc") if(APPLE) set(UBSAN_COMMON_SOURCES ${UBSAN_SOURCES}) diff --git a/lib/ubsan/Makefile.mk b/lib/ubsan/Makefile.mk deleted file mode 100644 index ec3f5c5da273..000000000000 --- a/lib/ubsan/Makefile.mk +++ /dev/null @@ -1,28 +0,0 @@ -#===- lib/ubsan/Makefile.mk ---------------------------------*- Makefile -*--===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# - -ModuleName := ubsan -SubDirs := - -Sources := $(foreach file,$(wildcard $(Dir)/*.cc),$(notdir $(file))) -StandaloneSources := ubsan_init_standalone.cc -CXXSources := ubsan_type_hash.cc ubsan_handlers_cxx.cc -CSources := $(filter-out $(StandaloneSources),$(filter-out $(CXXSources),$(Sources))) -ObjNames := $(Sources:%.cc=%.o) - -Implementation := Generic - -# FIXME: use automatic dependencies? -Dependencies := $(wildcard $(Dir)/*.h) -Dependencies += $(wildcard $(Dir)/../sanitizer_common/*.h) - -# Define a convenience variable for all the ubsan functions. -UbsanFunctions := $(CSources:%.cc=%) -UbsanCXXFunctions := $(CXXSources:%.cc=%) -UbsanStandaloneFunctions := $(StandaloneSources:%.cc=%) diff --git a/lib/ubsan/ubsan_diag.cc b/lib/ubsan/ubsan_diag.cc index 2476947dc914..d842694aa80f 100644 --- a/lib/ubsan/ubsan_diag.cc +++ b/lib/ubsan/ubsan_diag.cc @@ -124,108 +124,98 @@ Diag &Diag::operator<<(const Value &V) { } /// Hexadecimal printing for numbers too large for Printf to handle directly. -static void PrintHex(UIntMax Val) { +static void RenderHex(InternalScopedString *Buffer, UIntMax Val) { #if HAVE_INT128_T - Printf("0x%08x%08x%08x%08x", - (unsigned int)(Val >> 96), - (unsigned int)(Val >> 64), - (unsigned int)(Val >> 32), - (unsigned int)(Val)); + Buffer->append("0x%08x%08x%08x%08x", (unsigned int)(Val >> 96), + (unsigned int)(Val >> 64), (unsigned int)(Val >> 32), + (unsigned int)(Val)); #else UNREACHABLE("long long smaller than 64 bits?"); #endif } -static void renderLocation(Location Loc) { - InternalScopedString LocBuffer(1024); +static void RenderLocation(InternalScopedString *Buffer, Location Loc) { switch (Loc.getKind()) { case Location::LK_Source: { SourceLocation SLoc = Loc.getSourceLocation(); if (SLoc.isInvalid()) - LocBuffer.append("<unknown>"); + Buffer->append("<unknown>"); else - RenderSourceLocation(&LocBuffer, SLoc.getFilename(), SLoc.getLine(), + RenderSourceLocation(Buffer, SLoc.getFilename(), SLoc.getLine(), SLoc.getColumn(), common_flags()->symbolize_vs_style, common_flags()->strip_path_prefix); - break; + return; } case Location::LK_Memory: - LocBuffer.append("%p", Loc.getMemoryLocation()); - break; + Buffer->append("%p", Loc.getMemoryLocation()); + return; case Location::LK_Symbolized: { const AddressInfo &Info = Loc.getSymbolizedStack()->info; - if (Info.file) { - RenderSourceLocation(&LocBuffer, Info.file, Info.line, Info.column, + if (Info.file) + RenderSourceLocation(Buffer, Info.file, Info.line, Info.column, common_flags()->symbolize_vs_style, common_flags()->strip_path_prefix); - } else if (Info.module) { - RenderModuleLocation(&LocBuffer, Info.module, Info.module_offset, + else if (Info.module) + RenderModuleLocation(Buffer, Info.module, Info.module_offset, common_flags()->strip_path_prefix); - } else { - LocBuffer.append("%p", Info.address); - } - break; + else + Buffer->append("%p", Info.address); + return; } case Location::LK_Null: - LocBuffer.append("<unknown>"); - break; + Buffer->append("<unknown>"); + return; } - Printf("%s:", LocBuffer.data()); } -static void renderText(const char *Message, const Diag::Arg *Args) { +static void RenderText(InternalScopedString *Buffer, const char *Message, + const Diag::Arg *Args) { for (const char *Msg = Message; *Msg; ++Msg) { if (*Msg != '%') { - char Buffer[64]; - unsigned I; - for (I = 0; Msg[I] && Msg[I] != '%' && I != 63; ++I) - Buffer[I] = Msg[I]; - Buffer[I] = '\0'; - Printf(Buffer); - Msg += I - 1; - } else { - const Diag::Arg &A = Args[*++Msg - '0']; - switch (A.Kind) { - case Diag::AK_String: - Printf("%s", A.String); - break; - case Diag::AK_TypeName: { - if (SANITIZER_WINDOWS) - // The Windows implementation demangles names early. - Printf("'%s'", A.String); - else - Printf("'%s'", Symbolizer::GetOrInit()->Demangle(A.String)); - break; - } - case Diag::AK_SInt: - // 'long long' is guaranteed to be at least 64 bits wide. - if (A.SInt >= INT64_MIN && A.SInt <= INT64_MAX) - Printf("%lld", (long long)A.SInt); - else - PrintHex(A.SInt); - break; - case Diag::AK_UInt: - if (A.UInt <= UINT64_MAX) - Printf("%llu", (unsigned long long)A.UInt); - else - PrintHex(A.UInt); - break; - case Diag::AK_Float: { - // FIXME: Support floating-point formatting in sanitizer_common's - // printf, and stop using snprintf here. - char Buffer[32]; + Buffer->append("%c", *Msg); + continue; + } + const Diag::Arg &A = Args[*++Msg - '0']; + switch (A.Kind) { + case Diag::AK_String: + Buffer->append("%s", A.String); + break; + case Diag::AK_TypeName: { + if (SANITIZER_WINDOWS) + // The Windows implementation demangles names early. + Buffer->append("'%s'", A.String); + else + Buffer->append("'%s'", Symbolizer::GetOrInit()->Demangle(A.String)); + break; + } + case Diag::AK_SInt: + // 'long long' is guaranteed to be at least 64 bits wide. + if (A.SInt >= INT64_MIN && A.SInt <= INT64_MAX) + Buffer->append("%lld", (long long)A.SInt); + else + RenderHex(Buffer, A.SInt); + break; + case Diag::AK_UInt: + if (A.UInt <= UINT64_MAX) + Buffer->append("%llu", (unsigned long long)A.UInt); + else + RenderHex(Buffer, A.UInt); + break; + case Diag::AK_Float: { + // FIXME: Support floating-point formatting in sanitizer_common's + // printf, and stop using snprintf here. + char FloatBuffer[32]; #if SANITIZER_WINDOWS - sprintf_s(Buffer, sizeof(Buffer), "%Lg", (long double)A.Float); + sprintf_s(FloatBuffer, sizeof(FloatBuffer), "%Lg", (long double)A.Float); #else - snprintf(Buffer, sizeof(Buffer), "%Lg", (long double)A.Float); + snprintf(FloatBuffer, sizeof(FloatBuffer), "%Lg", (long double)A.Float); #endif - Printf("%s", Buffer); - break; - } - case Diag::AK_Pointer: - Printf("%p", A.Pointer); - break; - } + Buffer->append("%s", FloatBuffer); + break; + } + case Diag::AK_Pointer: + Buffer->append("%p", A.Pointer); + break; } } } @@ -253,9 +243,9 @@ static inline uptr addNoOverflow(uptr LHS, uptr RHS) { } /// Render a snippet of the address space near a location. -static void renderMemorySnippet(const Decorator &Decor, MemoryLocation Loc, - Range *Ranges, unsigned NumRanges, - const Diag::Arg *Args) { +static void PrintMemorySnippet(const Decorator &Decor, MemoryLocation Loc, + Range *Ranges, unsigned NumRanges, + const Diag::Arg *Args) { // Show at least the 8 bytes surrounding Loc. const unsigned MinBytesNearLoc = 4; MemoryLocation Min = subtractNoOverflow(Loc, MinBytesNearLoc); @@ -278,14 +268,15 @@ static void renderMemorySnippet(const Decorator &Decor, MemoryLocation Loc, } // Emit data. + InternalScopedString Buffer(1024); for (uptr P = Min; P != Max; ++P) { unsigned char C = *reinterpret_cast<const unsigned char*>(P); - Printf("%s%02x", (P % 8 == 0) ? " " : " ", C); + Buffer.append("%s%02x", (P % 8 == 0) ? " " : " ", C); } - Printf("\n"); + Buffer.append("\n"); // Emit highlights. - Printf(Decor.Highlight()); + Buffer.append(Decor.Highlight()); Range *InRange = upperBound(Min, Ranges, NumRanges); for (uptr P = Min; P != Max; ++P) { char Pad = ' ', Byte = ' '; @@ -297,10 +288,13 @@ static void renderMemorySnippet(const Decorator &Decor, MemoryLocation Loc, Pad = '~'; if (InRange && InRange->getStart().getMemoryLocation() <= P) Byte = '~'; - char Buffer[] = { Pad, Pad, P == Loc ? '^' : Byte, Byte, 0 }; - Printf((P % 8 == 0) ? Buffer : &Buffer[1]); + if (P % 8 == 0) + Buffer.append("%c", Pad); + Buffer.append("%c", Pad); + Buffer.append("%c", P == Loc ? '^' : Byte); + Buffer.append("%c", Byte); } - Printf("%s\n", Decor.EndHighlight()); + Buffer.append("%s\n", Decor.EndHighlight()); // Go over the line again, and print names for the ranges. InRange = 0; @@ -315,9 +309,9 @@ static void renderMemorySnippet(const Decorator &Decor, MemoryLocation Loc, if (InRange && InRange->getStart().getMemoryLocation() == P) { while (Spaces--) - Printf(" "); - renderText(InRange->getText(), Args); - Printf("\n"); + Buffer.append(" "); + RenderText(&Buffer, InRange->getText(), Args); + Buffer.append("\n"); // FIXME: We only support naming one range for now! break; } @@ -325,6 +319,7 @@ static void renderMemorySnippet(const Decorator &Decor, MemoryLocation Loc, Spaces += 2; } + Printf("%s", Buffer.data()); // FIXME: Print names for anything we can identify within the line: // // * If we can identify the memory itself as belonging to a particular @@ -341,28 +336,30 @@ Diag::~Diag() { // All diagnostics should be printed under report mutex. CommonSanitizerReportMutex.CheckLocked(); Decorator Decor; - Printf(Decor.Bold()); + InternalScopedString Buffer(1024); - renderLocation(Loc); + Buffer.append(Decor.Bold()); + RenderLocation(&Buffer, Loc); + Buffer.append(":"); switch (Level) { case DL_Error: - Printf("%s runtime error: %s%s", - Decor.Warning(), Decor.EndWarning(), Decor.Bold()); + Buffer.append("%s runtime error: %s%s", Decor.Warning(), Decor.EndWarning(), + Decor.Bold()); break; case DL_Note: - Printf("%s note: %s", Decor.Note(), Decor.EndNote()); + Buffer.append("%s note: %s", Decor.Note(), Decor.EndNote()); break; } - renderText(Message, Args); + RenderText(&Buffer, Message, Args); - Printf("%s\n", Decor.Default()); + Buffer.append("%s\n", Decor.Default()); + Printf("%s", Buffer.data()); if (Loc.isMemoryLocation()) - renderMemorySnippet(Decor, Loc.getMemoryLocation(), Ranges, - NumRanges, Args); + PrintMemorySnippet(Decor, Loc.getMemoryLocation(), Ranges, NumRanges, Args); } ScopedReport::ScopedReport(ReportOptions Opts, Location SummaryLoc, diff --git a/lib/ubsan/ubsan_flags.cc b/lib/ubsan/ubsan_flags.cc index 20087b968782..e77ba550148a 100644 --- a/lib/ubsan/ubsan_flags.cc +++ b/lib/ubsan/ubsan_flags.cc @@ -59,7 +59,7 @@ void InitializeFlags() { parser.ParseString(MaybeCallUbsanDefaultOptions()); // Override from environment variable. parser.ParseString(GetEnv("UBSAN_OPTIONS")); - SetVerbosity(common_flags()->verbosity); + InitializeCommonFlags(); if (Verbosity()) ReportUnrecognizedFlags(); if (common_flags()->help) parser.PrintFlagDescriptions(); diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc index 5d82e9afcd09..4ede388e03c8 100644 --- a/lib/ubsan/ubsan_handlers.cc +++ b/lib/ubsan/ubsan_handlers.cc @@ -523,8 +523,11 @@ void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) { Die(); } -static void handleCFIBadIcall(CFIBadIcallData *Data, ValueHandle Function, +static void handleCFIBadIcall(CFICheckFailData *Data, ValueHandle Function, ReportOptions Opts) { + if (Data->CheckKind != CFITCK_ICall) + Die(); + SourceLocation Loc = Data->Loc.acquire(); ErrorType ET = ErrorType::CFIBadType; @@ -544,16 +547,37 @@ static void handleCFIBadIcall(CFIBadIcallData *Data, ValueHandle Function, Diag(FLoc, DL_Note, "%0 defined here") << FName; } -void __ubsan::__ubsan_handle_cfi_bad_icall(CFIBadIcallData *Data, - ValueHandle Function) { +namespace __ubsan { +#ifdef UBSAN_CAN_USE_CXXABI +SANITIZER_WEAK_ATTRIBUTE +void HandleCFIBadType(CFICheckFailData *Data, ValueHandle Vtable, + bool ValidVtable, ReportOptions Opts); +#else +static void HandleCFIBadType(CFICheckFailData *Data, ValueHandle Vtable, + bool ValidVtable, ReportOptions Opts) { + Die(); +} +#endif +} // namespace __ubsan + +void __ubsan::__ubsan_handle_cfi_check_fail(CFICheckFailData *Data, + ValueHandle Value, + uptr ValidVtable) { GET_REPORT_OPTIONS(false); - handleCFIBadIcall(Data, Function, Opts); + if (Data->CheckKind == CFITCK_ICall) + handleCFIBadIcall(Data, Value, Opts); + else + HandleCFIBadType(Data, Value, ValidVtable, Opts); } -void __ubsan::__ubsan_handle_cfi_bad_icall_abort(CFIBadIcallData *Data, - ValueHandle Function) { +void __ubsan::__ubsan_handle_cfi_check_fail_abort(CFICheckFailData *Data, + ValueHandle Value, + uptr ValidVtable) { GET_REPORT_OPTIONS(true); - handleCFIBadIcall(Data, Function, Opts); + if (Data->CheckKind == CFITCK_ICall) + handleCFIBadIcall(Data, Value, Opts); + else + HandleCFIBadType(Data, Value, ValidVtable, Opts); Die(); } diff --git a/lib/ubsan/ubsan_handlers.h b/lib/ubsan/ubsan_handlers.h index 6f309cf9aaa9..e0cfd5b7057d 100644 --- a/lib/ubsan/ubsan_handlers.h +++ b/lib/ubsan/ubsan_handlers.h @@ -148,14 +148,25 @@ struct NonNullArgData { /// \brief Handle passing null pointer to function with nonnull attribute. RECOVERABLE(nonnull_arg, NonNullArgData *Data) -struct CFIBadIcallData { +/// \brief Known CFI check kinds. +/// Keep in sync with the enum of the same name in CodeGenFunction.h +enum CFITypeCheckKind : unsigned char { + CFITCK_VCall, + CFITCK_NVCall, + CFITCK_DerivedCast, + CFITCK_UnrelatedCast, + CFITCK_ICall, +}; + +struct CFICheckFailData { + CFITypeCheckKind CheckKind; SourceLocation Loc; const TypeDescriptor &Type; }; -/// \brief Handle control flow integrity failure for indirect function calls. -RECOVERABLE(cfi_bad_icall, CFIBadIcallData *Data, ValueHandle Function) - +/// \brief Handle control flow integrity failures. +RECOVERABLE(cfi_check_fail, CFICheckFailData *Data, ValueHandle Function, + uptr VtableIsValid) } #endif // UBSAN_HANDLERS_H diff --git a/lib/ubsan/ubsan_handlers_cxx.cc b/lib/ubsan/ubsan_handlers_cxx.cc index 3e81be67163b..d97ec4813ccd 100644 --- a/lib/ubsan/ubsan_handlers_cxx.cc +++ b/lib/ubsan/ubsan_handlers_cxx.cc @@ -15,6 +15,7 @@ #include "ubsan_platform.h" #if CAN_SANITIZE_UB +#include "ubsan_handlers.h" #include "ubsan_handlers_cxx.h" #include "ubsan_diag.h" #include "ubsan_type_hash.h" @@ -54,11 +55,17 @@ static bool HandleDynamicTypeCacheMiss( << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type; // If possible, say what type it actually points to. - if (!DTI.isValid()) - Diag(Pointer, DL_Note, "object has invalid vptr") - << TypeName(DTI.getMostDerivedTypeName()) - << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr"); - else if (!DTI.getOffset()) + if (!DTI.isValid()) { + if (DTI.getOffset() < -VptrMaxOffsetToTop || DTI.getOffset() > VptrMaxOffsetToTop) { + Diag(Pointer, DL_Note, "object has a possibly invalid vptr: abs(offset to top) too big") + << TypeName(DTI.getMostDerivedTypeName()) + << Range(Pointer, Pointer + sizeof(uptr), "possibly invalid vptr"); + } else { + Diag(Pointer, DL_Note, "object has invalid vptr") + << TypeName(DTI.getMostDerivedTypeName()) + << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr"); + } + } else if (!DTI.getOffset()) Diag(Pointer, DL_Note, "object is of type %0") << TypeName(DTI.getMostDerivedTypeName()) << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0"); @@ -87,8 +94,9 @@ void __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort( Die(); } -static void HandleCFIBadType(CFIBadTypeData *Data, ValueHandle Vtable, - ReportOptions Opts) { +namespace __ubsan { +void HandleCFIBadType(CFICheckFailData *Data, ValueHandle Vtable, + bool ValidVtable, ReportOptions Opts) { SourceLocation Loc = Data->Loc.acquire(); ErrorType ET = ErrorType::CFIBadType; @@ -96,38 +104,44 @@ static void HandleCFIBadType(CFIBadTypeData *Data, ValueHandle Vtable, return; ScopedReport R(Opts, Loc, ET); - DynamicTypeInfo DTI = getDynamicTypeInfoFromVtable((void*)Vtable); - - static const char *TypeCheckKinds[] = { - "virtual call", - "non-virtual call", - "base-to-derived cast", - "cast to unrelated type", - }; + DynamicTypeInfo DTI = ValidVtable + ? getDynamicTypeInfoFromVtable((void *)Vtable) + : DynamicTypeInfo(0, 0, 0); + + const char *CheckKindStr; + switch (Data->CheckKind) { + case CFITCK_VCall: + CheckKindStr = "virtual call"; + break; + case CFITCK_NVCall: + CheckKindStr = "non-virtual call"; + break; + case CFITCK_DerivedCast: + CheckKindStr = "base-to-derived cast"; + break; + case CFITCK_UnrelatedCast: + CheckKindStr = "cast to unrelated type"; + break; + case CFITCK_ICall: + Die(); + } Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during " "%1 (vtable address %2)") - << Data->Type << TypeCheckKinds[Data->TypeCheckKind] << (void *)Vtable; + << Data->Type << CheckKindStr << (void *)Vtable; // If possible, say what type it actually points to. - if (!DTI.isValid()) - Diag(Vtable, DL_Note, "invalid vtable"); - else + if (!DTI.isValid()) { + const char *module = Symbolizer::GetOrInit()->GetModuleNameForPc(Vtable); + if (module) + Diag(Vtable, DL_Note, "invalid vtable in module %0") << module; + else + Diag(Vtable, DL_Note, "invalid vtable"); + } else { Diag(Vtable, DL_Note, "vtable is of type %0") << TypeName(DTI.getMostDerivedTypeName()); + } } +} // namespace __ubsan -void __ubsan::__ubsan_handle_cfi_bad_type(CFIBadTypeData *Data, - ValueHandle Vtable) { - GET_REPORT_OPTIONS(false); - HandleCFIBadType(Data, Vtable, Opts); -} - -void __ubsan::__ubsan_handle_cfi_bad_type_abort(CFIBadTypeData *Data, - ValueHandle Vtable) { - GET_REPORT_OPTIONS(true); - HandleCFIBadType(Data, Vtable, Opts); - Die(); -} - -#endif // CAN_SANITIZE_UB +#endif // CAN_SANITIZE_UB diff --git a/lib/ubsan/ubsan_handlers_cxx.h b/lib/ubsan/ubsan_handlers_cxx.h index 92050d99e48e..2ff014edfcb0 100644 --- a/lib/ubsan/ubsan_handlers_cxx.h +++ b/lib/ubsan/ubsan_handlers_cxx.h @@ -25,12 +25,6 @@ struct DynamicTypeCacheMissData { unsigned char TypeCheckKind; }; -struct CFIBadTypeData { - SourceLocation Loc; - const TypeDescriptor &Type; - unsigned char TypeCheckKind; -}; - /// \brief Handle a runtime type check failure, caused by an incorrect vptr. /// When this handler is called, all we know is that the type was not in the /// cache; this does not necessarily imply the existence of a bug. @@ -40,14 +34,6 @@ void __ubsan_handle_dynamic_type_cache_miss( extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __ubsan_handle_dynamic_type_cache_miss_abort( DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash); - -/// \brief Handle a control flow integrity check failure by printing a -/// diagnostic. -extern "C" SANITIZER_INTERFACE_ATTRIBUTE void -__ubsan_handle_cfi_bad_type(CFIBadTypeData *Data, ValueHandle Vtable); -extern "C" SANITIZER_INTERFACE_ATTRIBUTE void -__ubsan_handle_cfi_bad_type_abort(CFIBadTypeData *Data, ValueHandle Vtable); - } #endif // UBSAN_HANDLERS_H diff --git a/lib/ubsan/ubsan_platform.h b/lib/ubsan/ubsan_platform.h index 002ecf32a595..1a3bfd6afb81 100644 --- a/lib/ubsan/ubsan_platform.h +++ b/lib/ubsan/ubsan_platform.h @@ -16,7 +16,8 @@ // Other platforms should be easy to add, and probably work as-is. #if (defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)) && \ (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || \ - defined(__aarch64__) || defined(__mips__) || defined(__powerpc64__)) + defined(__aarch64__) || defined(__mips__) || defined(__powerpc64__) || \ + defined(__s390__)) # define CAN_SANITIZE_UB 1 #elif defined(_WIN32) # define CAN_SANITIZE_UB 1 diff --git a/lib/ubsan/ubsan_type_hash.h b/lib/ubsan/ubsan_type_hash.h index 695fed905a73..aa638713f089 100644 --- a/lib/ubsan/ubsan_type_hash.h +++ b/lib/ubsan/ubsan_type_hash.h @@ -53,6 +53,10 @@ bool checkDynamicType(void *Object, void *Type, HashValue Hash); const unsigned VptrTypeCacheSize = 128; +/// A sanity check for Vtable. Offsets to top must be reasonably small +/// numbers (by absolute value). It's a weak check for Vtable corruption. +const int VptrMaxOffsetToTop = 1<<20; + /// \brief A cache of the results of checkDynamicType. \c checkDynamicType would /// return \c true (modulo hash collisions) if /// \code diff --git a/lib/ubsan/ubsan_type_hash_itanium.cc b/lib/ubsan/ubsan_type_hash_itanium.cc index b84e88d4c71d..26272e3360b2 100644 --- a/lib/ubsan/ubsan_type_hash_itanium.cc +++ b/lib/ubsan/ubsan_type_hash_itanium.cc @@ -115,7 +115,9 @@ static __ubsan::HashValue *getTypeCacheHashTableBucket(__ubsan::HashValue V) { static bool isDerivedFromAtOffset(const abi::__class_type_info *Derived, const abi::__class_type_info *Base, sptr Offset) { - if (Derived->__type_name == Base->__type_name) + if (Derived->__type_name == Base->__type_name || + (SANITIZER_NON_UNIQUE_TYPEINFO && + !internal_strcmp(Derived->__type_name, Base->__type_name))) return Offset == 0; if (const abi::__si_class_type_info *SI = @@ -219,6 +221,10 @@ bool __ubsan::checkDynamicType(void *Object, void *Type, HashValue Hash) { VtablePrefix *Vtable = getVtablePrefix(VtablePtr); if (!Vtable) return false; + if (Vtable->Offset < -VptrMaxOffsetToTop || Vtable->Offset > VptrMaxOffsetToTop) { + // Too large or too small offset are signs of Vtable corruption. + return false; + } // Check that this is actually a type_info object for a class type. abi::__class_type_info *Derived = @@ -241,6 +247,8 @@ __ubsan::getDynamicTypeInfoFromVtable(void *VtablePtr) { VtablePrefix *Vtable = getVtablePrefix(VtablePtr); if (!Vtable) return DynamicTypeInfo(0, 0, 0); + if (Vtable->Offset < -VptrMaxOffsetToTop || Vtable->Offset > VptrMaxOffsetToTop) + return DynamicTypeInfo(0, Vtable->Offset, 0); const abi::__class_type_info *ObjectType = findBaseAtOffset( static_cast<const abi::__class_type_info*>(Vtable->TypeInfo), -Vtable->Offset); diff --git a/lib/ubsan/ubsan_value.cc b/lib/ubsan/ubsan_value.cc index 79dc4c8e8271..466834c09ed1 100644 --- a/lib/ubsan/ubsan_value.cc +++ b/lib/ubsan/ubsan_value.cc @@ -83,12 +83,12 @@ FloatMax Value::getFloatValue() const { #endif case 32: { float Value; -#if defined(__BIG_ENDIAN__) +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ // For big endian the float value is in the last 4 bytes. // On some targets we may only have 4 bytes so we count backwards from // the end of Val to account for both the 32-bit and 64-bit cases. internal_memcpy(&Value, ((const char*)(&Val + 1)) - 4, 4); -#else +#else internal_memcpy(&Value, &Val, 4); #endif return Value; |