Skip to content

[rtsan] Add support for ReportErrorSummary #116424

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 19, 2024
Merged

Conversation

cjappl
Copy link
Contributor

@cjappl cjappl commented Nov 15, 2024

Adding support for the extra SUMMARY line that is output by most compilers. This also adds the ability for end-users to specify their own handlers for reporting these errors (see the test).

The output for a basic error will look something like this, where the SUMMARY line is a new addition

> ./build/helloWorld
==82636==ERROR: RealtimeSanitizer: unsafe-library-call
Intercepted call to real-time unsafe function `malloc` in real-time context!
    #0 0x000102716620 in malloc rtsan_interceptors_posix.cpp:445
    #1 0x0001021822a8 in process(std::__1::vector<int, std::__1::allocator<int>>&) main.cpp:8
    #2 0x0001021822e8 in main main.cpp:15
    #3 0x00018d8860dc  (<unknown module>)
    #4 0x8d617ffffffffffc  (<unknown module>)

SUMMARY: RealtimeSanitizer: unsafe-library-call main.cpp:8 in process(std::__1::vector<int, std::__1::allocator<int>>&)

This compares to something like asan, for instance:

> ./build/helloWorld
helloWorld(91968,0x1f5a48c00) malloc: nano zone abandoned due to inability to reserve vm space.
=================================================================
==91968==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6140000001d0 at pc 0x000100d9be58 bp 0x00016f066950 sp 0x00016f066948
WRITE of size 4 at 0x6140000001d0 thread T0
    #0 0x000100d9be54 in violation() main.cpp:17
    #1 0x000100d9be90 in main main.cpp:23
    #2 0x00018d8860dc  (<unknown module>)
    #3 0xe4197ffffffffffc  (<unknown module>)

0x6140000001d0 is located 0 bytes after 400-byte region [0x614000000040,0x6140000001d0)
allocated by thread T0 here:
    #0 0x0001015fc7dc in _Znam asan_new_delete.cpp:114
    #1 0x000100d9be00 in violation() main.cpp:16
    #2 0x000100d9be90 in main main.cpp:23
    #3 0x00018d8860dc  (<unknown module>)
    #4 0xe4197ffffffffffc  (<unknown module>)

SUMMARY: AddressSanitizer: heap-buffer-overflow main.cpp:17 in violation()
...

PrintDiagnostics(info);
stack.Print();
{
ScopedErrorReportLock l;
Copy link
Contributor Author

@cjappl cjappl Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lock is now bubbled up here to make sure we don't ever separate any of this reporting across threads, we then just assert the lock has been taken in debug mode later in these methods

@llvmbot
Copy link
Member

llvmbot commented Nov 16, 2024

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Chris Apple (cjappl)

Changes

Adding support for the extra SUMMARY line that is output by most compilers. This also adds the ability for end-users to specify their own handlers for reporting these errors (see the test).

The output for a basic error will look something like this, where the SUMMARY line is a new addition

&gt; ./build/helloWorld
==82636==ERROR: RealtimeSanitizer: unsafe-library-call
Intercepted call to real-time unsafe function `malloc` in real-time context!
    #<!-- -->0 0x000102716620 in malloc rtsan_interceptors_posix.cpp:445
    #<!-- -->1 0x0001021822a8 in process(std::__1::vector&lt;int, std::__1::allocator&lt;int&gt;&gt;&amp;) main.cpp:8
    #<!-- -->2 0x0001021822e8 in main main.cpp:15
    #<!-- -->3 0x00018d8860dc  (&lt;unknown module&gt;)
    #<!-- -->4 0x8d617ffffffffffc  (&lt;unknown module&gt;)

SUMMARY: RealtimeSanitizer: unsafe-library-call main.cpp:8 in process(std::__1::vector&lt;int, std::__1::allocator&lt;int&gt;&gt;&amp;)

This compares to something like asan, for instance:

&gt; ./build/helloWorld
helloWorld(91968,0x1f5a48c00) malloc: nano zone abandoned due to inability to reserve vm space.
=================================================================
==91968==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6140000001d0 at pc 0x000100d9be58 bp 0x00016f066950 sp 0x00016f066948
WRITE of size 4 at 0x6140000001d0 thread T0
    #<!-- -->0 0x000100d9be54 in violation() main.cpp:17
    #<!-- -->1 0x000100d9be90 in main main.cpp:23
    #<!-- -->2 0x00018d8860dc  (&lt;unknown module&gt;)
    #<!-- -->3 0xe4197ffffffffffc  (&lt;unknown module&gt;)

0x6140000001d0 is located 0 bytes after 400-byte region [0x614000000040,0x6140000001d0)
allocated by thread T0 here:
    #<!-- -->0 0x0001015fc7dc in _Znam asan_new_delete.cpp:114
    #<!-- -->1 0x000100d9be00 in violation() main.cpp:16
    #<!-- -->2 0x000100d9be90 in main main.cpp:23
    #<!-- -->3 0x00018d8860dc  (&lt;unknown module&gt;)
    #<!-- -->4 0xe4197ffffffffffc  (&lt;unknown module&gt;)

SUMMARY: AddressSanitizer: heap-buffer-overflow main.cpp:17 in violation()
...

Full diff: https://github.com/llvm/llvm-project/pull/116424.diff

4 Files Affected:

  • (modified) compiler-rt/lib/rtsan/rtsan.cpp (+6-2)
  • (modified) compiler-rt/lib/rtsan/rtsan_diagnostics.cpp (+19-11)
  • (modified) compiler-rt/lib/rtsan/rtsan_diagnostics.h (+2)
  • (added) compiler-rt/test/rtsan/report_error_summary.cpp (+32)
diff --git a/compiler-rt/lib/rtsan/rtsan.cpp b/compiler-rt/lib/rtsan/rtsan.cpp
index e9f42d3760aa82..70edcc546219fa 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 ecba30d2ab8df5..f13d3db101d487 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 f8a6b8a954a24a..1138e61eb5df4c 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 00000000000000..9da7f217f61bfa
--- /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 <stdio.h>
+#include <stdlib.h>
+
+#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

@cjappl cjappl merged commit 7c41b5c into llvm:main Nov 19, 2024
9 checks passed
@cjappl cjappl deleted the error_summary branch November 19, 2024 22:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants