diff options
author | Alexey Samsonov <vonosmas@gmail.com> | 2014-09-19 18:33:45 +0000 |
---|---|---|
committer | Alexey Samsonov <vonosmas@gmail.com> | 2014-09-19 18:33:45 +0000 |
commit | a82d43abfe5ac2c3067bbd71a17bb94cd5d4ba1f (patch) | |
tree | e98c5bf0b48130caef75e09a8f8b2c72aefe235b | |
parent | 2bc599a96d1e7cb308b470fa18f6df45e7561a50 (diff) |
[UBSan] Optionally report summary in UBSan error reports.
By default summary is not printed if UBSan is run in a standalone mode,
but is printed if it's combined with another sanitizer (like ASan).
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@218135 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.h | 2 | ||||
-rw-r--r-- | lib/ubsan/ubsan_diag.cc | 20 | ||||
-rw-r--r-- | lib/ubsan/ubsan_diag.h | 3 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers.cc | 35 | ||||
-rw-r--r-- | lib/ubsan/ubsan_handlers_cxx.cc | 2 | ||||
-rw-r--r-- | test/ubsan/TestCases/Integer/summary.cpp | 10 | ||||
-rw-r--r-- | test/ubsan/lit.common.cfg | 2 |
7 files changed, 53 insertions, 21 deletions
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index c85264aef..cf41b5a9a 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -250,7 +250,7 @@ const int kMaxSummaryLength = 1024; // and pass it to __sanitizer_report_error_summary. void ReportErrorSummary(const char *error_message); // Same as above, but construct error_message as: -// error_type: file:line function +// error_type file:line function void ReportErrorSummary(const char *error_type, const char *file, int line, const char *function); void ReportErrorSummary(const char *error_type, StackTrace *trace); diff --git a/lib/ubsan/ubsan_diag.cc b/lib/ubsan/ubsan_diag.cc index ea2fa9b44..33babaf3d 100644 --- a/lib/ubsan/ubsan_diag.cc +++ b/lib/ubsan/ubsan_diag.cc @@ -38,6 +38,22 @@ static void MaybePrintStackTrace(uptr pc, uptr bp) { stack.Print(); } +static void MaybeReportErrorSummary(Location Loc) { + if (!common_flags()->print_summary) + return; + // Don't try to unwind the stack trace in UBSan summaries: just use the + // provided location. + if (Loc.isSourceLocation()) { + SourceLocation SLoc = Loc.getSourceLocation(); + if (!SLoc.isInvalid()) { + ReportErrorSummary("runtime-error", SLoc.getFilename(), SLoc.getLine(), + ""); + return; + } + } + ReportErrorSummary("runtime-error"); +} + namespace { class Decorator : public SanitizerCommonDecorator { public: @@ -315,13 +331,15 @@ Diag::~Diag() { NumRanges, Args); } -ScopedReport::ScopedReport(ReportOptions Opts) : Opts(Opts) { +ScopedReport::ScopedReport(ReportOptions Opts, Location SummaryLoc) + : Opts(Opts), SummaryLoc(SummaryLoc) { InitIfNecessary(); CommonSanitizerReportMutex.Lock(); } ScopedReport::~ScopedReport() { MaybePrintStackTrace(Opts.pc, Opts.bp); + MaybeReportErrorSummary(SummaryLoc); CommonSanitizerReportMutex.Unlock(); if (Opts.DieAfterReport || flags()->halt_on_error) Die(); diff --git a/lib/ubsan/ubsan_diag.h b/lib/ubsan/ubsan_diag.h index b2fe735a2..296ec0d3f 100644 --- a/lib/ubsan/ubsan_diag.h +++ b/lib/ubsan/ubsan_diag.h @@ -223,9 +223,10 @@ struct ReportOptions { /// different sanitizers won't be mixed. class ScopedReport { ReportOptions Opts; + Location SummaryLoc; public: - ScopedReport(ReportOptions Opts); + ScopedReport(ReportOptions Opts, Location SummaryLoc); ~ScopedReport(); }; diff --git a/lib/ubsan/ubsan_handlers.cc b/lib/ubsan/ubsan_handlers.cc index f6d1a0eeb..f8365a7d2 100644 --- a/lib/ubsan/ubsan_handlers.cc +++ b/lib/ubsan/ubsan_handlers.cc @@ -43,11 +43,11 @@ static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer, if (ignoreReport(Loc.getSourceLocation(), Opts)) return; - ScopedReport R(Opts); - if (Data->Loc.isInvalid()) Loc = FallbackLoc; + ScopedReport R(Opts, Loc); + if (!Pointer) Diag(Loc, DL_Error, "%0 null pointer of type %1") << TypeCheckKinds[Data->TypeCheckKind] << Data->Type; @@ -85,7 +85,7 @@ static void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS, if (ignoreReport(Loc, Opts)) return; - ScopedReport R(Opts); + ScopedReport R(Opts, Loc); Diag(Loc, DL_Error, "%0 integer overflow: " "%1 %2 %3 cannot be represented in type %4") @@ -114,7 +114,7 @@ static void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal, if (ignoreReport(Loc, Opts)) return; - ScopedReport R(Opts); + ScopedReport R(Opts, Loc); if (Data->Type.isSignedIntegerTy()) Diag(Loc, DL_Error, @@ -145,7 +145,7 @@ static void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS, if (ignoreReport(Loc, Opts)) return; - ScopedReport R(Opts); + ScopedReport R(Opts, Loc); Value LHSVal(Data->Type, LHS); Value RHSVal(Data->Type, RHS); @@ -177,7 +177,7 @@ static void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data, if (ignoreReport(Loc, Opts)) return; - ScopedReport R(Opts); + ScopedReport R(Opts, Loc); Value LHSVal(Data->LHSType, LHS); Value RHSVal(Data->RHSType, RHS); @@ -216,7 +216,7 @@ static void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index, if (ignoreReport(Loc, Opts)) return; - ScopedReport R(Opts); + ScopedReport R(Opts, Loc); Value IndexVal(Data->IndexType, Index); Diag(Loc, DL_Error, "index %0 out of bounds for type %1") @@ -237,7 +237,7 @@ void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data, static void handleBuiltinUnreachableImpl(UnreachableData *Data, ReportOptions Opts) { - ScopedReport R(Opts); + ScopedReport R(Opts, Data->Loc); Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call"); } @@ -248,7 +248,7 @@ void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) { } static void handleMissingReturnImpl(UnreachableData *Data, ReportOptions Opts) { - ScopedReport R(Opts); + ScopedReport R(Opts, Data->Loc); Diag(Data->Loc, DL_Error, "execution reached the end of a value-returning function " "without returning a value"); @@ -266,7 +266,7 @@ static void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound, if (ignoreReport(Loc, Opts)) return; - ScopedReport R(Opts); + ScopedReport R(Opts, Loc); Diag(Loc, DL_Error, "variable length array bound evaluates to " "non-positive value %0") @@ -288,11 +288,12 @@ void __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data, static void handleFloatCastOverflow(FloatCastOverflowData *Data, ValueHandle From, ReportOptions Opts) { // TODO: Add deduplication once a SourceLocation is generated for this check. - ScopedReport R(Opts); + Location Loc = getCallerLocation(); + ScopedReport R(Opts, Loc); - Diag(getCallerLocation(), DL_Error, + Diag(Loc, DL_Error, "value %0 is outside the range of representable values of type %2") - << Value(Data->FromType, From) << Data->FromType << Data->ToType; + << Value(Data->FromType, From) << Data->FromType << Data->ToType; } void __ubsan::__ubsan_handle_float_cast_overflow(FloatCastOverflowData *Data, @@ -314,7 +315,7 @@ static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val, if (ignoreReport(Loc, Opts)) return; - ScopedReport R(Opts); + ScopedReport R(Opts, Loc); Diag(Loc, DL_Error, "load of value %0, which is not a valid value for type %1") @@ -340,7 +341,7 @@ static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data, Location Loc = getFunctionLocation(Function, &FName); - ScopedReport R(Opts); + ScopedReport R(Opts, Loc); Diag(Data->Loc, DL_Error, "call to function %0 through pointer to incorrect function type %1") @@ -367,7 +368,7 @@ static void handleNonNullReturn(NonNullReturnData *Data, ReportOptions Opts) { if (ignoreReport(Loc, Opts)) return; - ScopedReport R(Opts); + ScopedReport R(Opts, Loc); Diag(Loc, DL_Error, "null pointer returned from function declared to never " "return null"); @@ -391,7 +392,7 @@ static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts) { if (ignoreReport(Loc, Opts)) return; - ScopedReport R(Opts); + ScopedReport R(Opts, Loc); Diag(Loc, DL_Error, "null pointer passed as argument %0, which is declared to " "never be null") << Data->ArgIndex; diff --git a/lib/ubsan/ubsan_handlers_cxx.cc b/lib/ubsan/ubsan_handlers_cxx.cc index fa244c85d..5704c1e63 100644 --- a/lib/ubsan/ubsan_handlers_cxx.cc +++ b/lib/ubsan/ubsan_handlers_cxx.cc @@ -44,7 +44,7 @@ static void HandleDynamicTypeCacheMiss( if (Loc.isDisabled()) return; - ScopedReport R(Opts); + ScopedReport R(Opts, Loc); Diag(Loc, DL_Error, "%0 address %1 which does not point to an object of type %2") diff --git a/test/ubsan/TestCases/Integer/summary.cpp b/test/ubsan/TestCases/Integer/summary.cpp new file mode 100644 index 000000000..d6fecd2ab --- /dev/null +++ b/test/ubsan/TestCases/Integer/summary.cpp @@ -0,0 +1,10 @@ +// RUN: %clangxx -fsanitize=integer %s -o %t && %t 2>&1 | FileCheck %s +// REQUIRES: ubsan-asan + +#include <stdint.h> + +int main() { + (void)(uint64_t(10000000000000000000ull) + uint64_t(9000000000000000000ull)); + // CHECK: SUMMARY: AddressSanitizer: runtime-error {{.*}}summary.cpp:[[@LINE-1]] + return 0; +} diff --git a/test/ubsan/lit.common.cfg b/test/ubsan/lit.common.cfg index 4e3e377f0..b91b4bf5a 100644 --- a/test/ubsan/lit.common.cfg +++ b/test/ubsan/lit.common.cfg @@ -18,9 +18,11 @@ config.test_source_root = os.path.dirname(__file__) ubsan_lit_test_mode = get_required_attr(config, 'ubsan_lit_test_mode') if ubsan_lit_test_mode == "Standalone": config.name = 'UndefinedBehaviorSanitizer-Standalone' + config.available_features.add("ubsan-standalone") clang_ubsan_cflags = [] elif ubsan_lit_test_mode == "AddressSanitizer": config.name = 'UndefinedBehaviorSanitizer-AddressSanitizer' + config.available_features.add("ubsan-asan") clang_ubsan_cflags = ["-fsanitize=address"] config.environment['ASAN_OPTIONS'] = 'detect_leaks=0' else: |