Index: lib/ubsan/lit_tests/AsanConfig/lit.cfg =================================================================== --- lib/ubsan/lit_tests/AsanConfig/lit.cfg +++ lib/ubsan/lit_tests/AsanConfig/lit.cfg @@ -16,6 +16,7 @@ lit_config.load_config(config, ubsan_lit_cfg) config.name = 'UndefinedBehaviorSanitizer-AddressSanitizer' +config.available_features.add("ubsan-asan") # Define %clang and %clangxx substitutions to use in test RUN lines. config.substitutions.append( ("%clang ", (" " + config.clang + Index: lib/ubsan/lit_tests/TestCases/Integer/summary.cpp =================================================================== --- /dev/null +++ lib/ubsan/lit_tests/TestCases/Integer/summary.cpp @@ -0,0 +1,10 @@ +// RUN: %clangxx -fsanitize=integer %s -o %t && %t 2>&1 | FileCheck %s + +// REQUIRES: ubsan-asan + +#include + +int main() { + (void)(uint64_t(10000000000000000000ull) + uint64_t(9000000000000000000ull)); + // CHECK: SUMMARY: AddressSanitizer: runtime-error: {{.*}}summary.cpp:[[@LINE-1]] +} Index: lib/ubsan/lit_tests/UbsanConfig/lit.cfg =================================================================== --- lib/ubsan/lit_tests/UbsanConfig/lit.cfg +++ lib/ubsan/lit_tests/UbsanConfig/lit.cfg @@ -16,6 +16,7 @@ lit_config.load_config(config, ubsan_lit_cfg) config.name = 'UndefinedBehaviorSanitizer-Standalone' +config.available_features.add("ubsan-standalone") # Define %clang and %clangxx substitutions to use in test RUN lines. config.substitutions.append( ("%clang ", (" " + config.clang + " ")) ) Index: lib/ubsan/ubsan_diag.h =================================================================== --- lib/ubsan/ubsan_diag.h +++ lib/ubsan/ubsan_diag.h @@ -203,6 +203,9 @@ Diag &operator<<(const Range &R) { return AddRange(R); } }; +/// Optionally constructs and reports SUMMARY line like another sanitizers. +void ReportSummary(Location Loc); + } // namespace __ubsan #endif // UBSAN_DIAG_H Index: lib/ubsan/ubsan_diag.cc =================================================================== --- lib/ubsan/ubsan_diag.cc +++ lib/ubsan/ubsan_diag.cc @@ -13,6 +13,7 @@ #include "ubsan_diag.h" #include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_report_decorator.h" #include "sanitizer_common/sanitizer_stacktrace.h" @@ -76,8 +77,7 @@ #endif } -static void renderLocation(Location Loc) { - InternalScopedString LocBuffer(1024); +static void renderLocation(Location Loc, InternalScopedString &LocBuffer) { switch (Loc.getKind()) { case Location::LK_Source: { SourceLocation SLoc = Loc.getSourceLocation(); @@ -99,7 +99,6 @@ LocBuffer.append(""); break; } - Printf("%s:", LocBuffer.data()); } static void renderText(const char *Message, const Diag::Arg *Args) { @@ -250,7 +249,9 @@ SpinMutexLock l(&CommonSanitizerReportMutex); Printf(Decor.Bold()); - renderLocation(Loc); + InternalScopedString LocBuffer(1024); + renderLocation(Loc, LocBuffer); + Printf("%s:", LocBuffer.data()); switch (Level) { case DL_Error: @@ -271,3 +272,30 @@ renderMemorySnippet(Decor, Loc.getMemoryLocation(), Ranges, NumRanges, Args); } + +static void Initialize() { + static StaticSpinMutex init_mu; + SpinMutexLock l(&init_mu); + static bool initialized; + if (initialized) + return; + if (0 == internal_strcmp(SanitizerToolName, "SanitizerTool")) { + // UBSan is run in a standalone mode. Initialize it now. + SanitizerToolName = "UndefinedBehaviorSanitizer"; + CommonFlags *cf = common_flags(); + SetCommonFlagDefaults(); + cf->print_summary = false; + } + initialized = true; +} + +void __ubsan::ReportSummary(Location Loc) { + // FIXME: We may need to run initialization earlier. + Initialize(); + if (!common_flags()->print_summary) + return; + InternalScopedString SummaryBuffer(1024); + SummaryBuffer.append("runtime-error: "); + renderLocation(Loc, SummaryBuffer); + ReportErrorSummary(SummaryBuffer.data()); +} Index: lib/ubsan/ubsan_handlers.cc =================================================================== --- lib/ubsan/ubsan_handlers.cc +++ lib/ubsan/ubsan_handlers.cc @@ -50,6 +50,7 @@ << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type; if (Pointer) Diag(Pointer, DL_Note, "pointer points here"); + ReportSummary(Loc); } void __ubsan::__ubsan_handle_type_mismatch(TypeMismatchData *Data, ValueHandle Pointer) { @@ -74,6 +75,7 @@ "%1 %2 %3 cannot be represented in type %4") << (Data->Type.isSignedIntegerTy() ? "signed" : "unsigned") << Value(Data->Type, LHS) << Operator << RHS << Data->Type; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_add_overflow(OverflowData *Data, @@ -124,6 +126,7 @@ Diag(Loc, DL_Error, "negation of %0 cannot be represented in type %1") << Value(Data->Type, OldVal) << Data->Type; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data, ValueHandle OldVal) { @@ -145,6 +148,7 @@ << LHSVal << Data->Type; else Diag(Loc, DL_Error, "division by zero"); + ReportSummary(Loc); } void __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data, ValueHandle LHS, @@ -174,6 +178,7 @@ Diag(Loc, DL_Error, "left shift of %0 by %1 places cannot be represented in type %2") << LHSVal << RHSVal << Data->LHSType; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_shift_out_of_bounds_abort( ShiftOutOfBoundsData *Data, @@ -192,6 +197,7 @@ Value IndexVal(Data->IndexType, Index); Diag(Loc, DL_Error, "index %0 out of bounds for type %1") << IndexVal << Data->ArrayType; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data, ValueHandle Index) { @@ -200,14 +206,24 @@ } void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) { - Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call"); + SourceLocation Loc = Data->Loc.acquire(); + if (Loc.isDisabled()) + return; + + Diag(Loc, DL_Error, "execution reached a __builtin_unreachable() call"); + ReportSummary(Loc); Die(); } void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) { - Diag(Data->Loc, DL_Error, + SourceLocation Loc = Data->Loc.acquire(); + if (Loc.isDisabled()) + return; + + Diag(Loc, DL_Error, "execution reached the end of a value-returning function " "without returning a value"); + ReportSummary(Loc); Die(); } @@ -220,6 +236,7 @@ Diag(Loc, DL_Error, "variable length array bound evaluates to " "non-positive value %0") << Value(Data->Type, Bound); + ReportSummary(Loc); } void __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data, ValueHandle Bound) { @@ -231,16 +248,20 @@ void __ubsan::__ubsan_handle_float_cast_overflow(FloatCastOverflowData *Data, ValueHandle From) { // TODO: Add deduplication once a SourceLocation is generated for this check. - Diag(getCallerLocation(), DL_Error, + Location Loc = getCallerLocation(); + Diag(Loc, DL_Error, "value %0 is outside the range of representable values of type %2") << Value(Data->FromType, From) << Data->FromType << Data->ToType; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_float_cast_overflow_abort( FloatCastOverflowData *Data, ValueHandle From) { - Diag(getCallerLocation(), DL_Error, + Location Loc = getCallerLocation(); + Diag(Loc, DL_Error, "value %0 is outside the range of representable values of type %2") << Value(Data->FromType, From) << Data->FromType << Data->ToType; + ReportSummary(Loc); Die(); } @@ -253,6 +274,7 @@ Diag(Loc, DL_Error, "load of value %0, which is not a valid value for type %1") << Value(Data->Type, Val) << Data->Type; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data, ValueHandle Val) { @@ -271,6 +293,7 @@ "call to function %0 through pointer to incorrect function type %1") << FName << Data->Type; Diag(Loc, DL_Note, "%0 defined here") << FName; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_function_type_mismatch_abort( Index: lib/ubsan/ubsan_handlers_cxx.cc =================================================================== --- lib/ubsan/ubsan_handlers_cxx.cc +++ lib/ubsan/ubsan_handlers_cxx.cc @@ -60,6 +60,7 @@ << MangledName(DTI.getSubobjectTypeName()) << Range(Pointer, Pointer + sizeof(uptr), "vptr for %2 base class of %1"); + ReportSummary(Loc); if (Abort) Die(); }