diff --git a/compiler-rt/lib/rtsan/rtsan.cpp b/compiler-rt/lib/rtsan/rtsan.cpp index e9f42d3760aa8..70edcc546219f 100644 --- a/compiler-rt/lib/rtsan/rtsan.cpp +++ b/compiler-rt/lib/rtsan/rtsan.cpp @@ -62,8 +62,12 @@ static void OnViolation(const BufferedStackTrace &stack, if (UNLIKELY(is_stack_novel)) { IncrementUniqueErrorCount(); - PrintDiagnostics(info); - stack.Print(); + { + ScopedErrorReportLock l; + PrintDiagnostics(info); + stack.Print(); + PrintErrorSummary(info, stack); + } handle.inc_use_count_unsafe(); } diff --git a/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp b/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp index ecba30d2ab8df..f13d3db101d48 100644 --- a/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp +++ b/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp @@ -39,20 +39,22 @@ class Decorator : public SanitizerCommonDecorator { }; } // namespace +static const char *GetErrorTypeStr(const DiagnosticsInfo &info) { + switch (info.type) { + case DiagnosticsInfoType::InterceptedCall: + return "unsafe-library-call"; + case DiagnosticsInfoType::BlockingCall: + return "blocking-call"; + } + CHECK(false); + return "(unknown error)"; +} + static void PrintError(const Decorator &decorator, const DiagnosticsInfo &info) { - const auto ErrorTypeStr = [&info]() -> const char * { - switch (info.type) { - case DiagnosticsInfoType::InterceptedCall: - return "unsafe-library-call"; - case DiagnosticsInfoType::BlockingCall: - return "blocking-call"; - } - return "(unknown error)"; - }; Printf("%s", decorator.Error()); - Report("ERROR: RealtimeSanitizer: %s\n", ErrorTypeStr()); + Report("ERROR: RealtimeSanitizer: %s\n", GetErrorTypeStr(info)); } static void PrintReason(const Decorator &decorator, @@ -78,10 +80,16 @@ static void PrintReason(const Decorator &decorator, } void __rtsan::PrintDiagnostics(const DiagnosticsInfo &info) { - ScopedErrorReportLock l; + ScopedErrorReportLock::CheckLocked(); Decorator d; PrintError(d, info); PrintReason(d, info); Printf("%s", d.Default()); } + +void __rtsan::PrintErrorSummary(const DiagnosticsInfo &info, + const BufferedStackTrace &stack) { + ScopedErrorReportLock::CheckLocked(); + ReportErrorSummary(GetErrorTypeStr(info), &stack); +} diff --git a/compiler-rt/lib/rtsan/rtsan_diagnostics.h b/compiler-rt/lib/rtsan/rtsan_diagnostics.h index f8a6b8a954a24..1138e61eb5df4 100644 --- a/compiler-rt/lib/rtsan/rtsan_diagnostics.h +++ b/compiler-rt/lib/rtsan/rtsan_diagnostics.h @@ -30,4 +30,6 @@ struct DiagnosticsInfo { }; void PrintDiagnostics(const DiagnosticsInfo &info); +void PrintErrorSummary(const DiagnosticsInfo &info, + const __sanitizer::BufferedStackTrace &stack); } // namespace __rtsan diff --git a/compiler-rt/test/rtsan/report_error_summary.cpp b/compiler-rt/test/rtsan/report_error_summary.cpp new file mode 100644 index 0000000000000..9da7f217f61bf --- /dev/null +++ b/compiler-rt/test/rtsan/report_error_summary.cpp @@ -0,0 +1,32 @@ +// RUN: %clangxx -fsanitize=realtime %s -o %t +// RUN: %env_rtsan_opts="halt_on_error=false" %run %t 2>&1 | FileCheck %s + +// RUN: %clangxx -DTEST_CUSTOM_HANDLER=1 -fsanitize=realtime %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-CUSTOM-HANDLER + +// UNSUPPORTED: ios + +// Intent: Make sure we support ReporErrorSummary, including custom handlers + +#include +#include + +#ifdef TEST_CUSTOM_HANDLER +extern "C" void __sanitizer_report_error_summary(const char *error_summary) { + fprintf(stderr, "%s %s\n", "In custom handler! ", error_summary); +} +#endif + +int blocking_call() [[clang::blocking]] { return 0; } + +int main() [[clang::nonblocking]] { + void *ptr = malloc(2); + blocking_call(); + + printf("ptr: %p\n", ptr); // ensure we don't optimize out the malloc +} + +// CHECK: SUMMARY: RealtimeSanitizer: unsafe-library-call +// CHECK: SUMMARY: RealtimeSanitizer: blocking-call + +// CHECK-CUSTOM-HANDLER: In custom handler! SUMMARY: RealtimeSanitizer: unsafe-library-call