[asan] Provide bug descriptions for all reports (not just ErrorGeneric)
authorKuba Mracek <mracek@apple.com>
Mon, 28 Nov 2016 21:18:15 +0000 (21:18 +0000)
committerKuba Mracek <mracek@apple.com>
Mon, 28 Nov 2016 21:18:15 +0000 (21:18 +0000)
Differential Revision: https://reviews.llvm.org/D27012

llvm-svn: 288065

compiler-rt/lib/asan/asan_errors.cc
compiler-rt/lib/asan/asan_errors.h
compiler-rt/lib/asan/asan_report.cc
compiler-rt/test/asan/TestCases/debug_double_free.cc [new file with mode: 0644]

index 7f754d5..c287ba1 100644 (file)
@@ -26,8 +26,8 @@ void ErrorStackOverflow::Print() {
   Decorator d;
   Printf("%s", d.Warning());
   Report(
-      "ERROR: AddressSanitizer: stack-overflow on address %p"
-      " (pc %p bp %p sp %p T%d)\n",
+      "ERROR: AddressSanitizer: %s on address %p"
+      " (pc %p bp %p sp %p T%d)\n", scariness.GetDescription(),
       (void *)addr, (void *)pc, (void *)bp, (void *)sp, tid);
   Printf("%s", d.EndWarning());
   scariness.Print();
@@ -35,7 +35,7 @@ void ErrorStackOverflow::Print() {
   GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context,
                                   common_flags()->fast_unwind_on_fatal);
   stack.Print();
-  ReportErrorSummary("stack-overflow", &stack);
+  ReportErrorSummary(scariness.GetDescription(), &stack);
 }
 
 static void MaybeDumpInstructionBytes(uptr pc) {
@@ -93,9 +93,9 @@ void ErrorDoubleFree::Print() {
   Printf("%s", d.Warning());
   char tname[128];
   Report(
-      "ERROR: AddressSanitizer: attempting double-free on %p in "
+      "ERROR: AddressSanitizer: attempting %s on %p in "
       "thread T%d%s:\n",
-      addr_description.addr, tid,
+      scariness.GetDescription(), addr_description.addr, tid,
       ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
   Printf("%s", d.EndWarning());
   scariness.Print();
@@ -103,7 +103,7 @@ void ErrorDoubleFree::Print() {
                         second_free_stack->top_frame_bp);
   stack.Print();
   addr_description.Print();
-  ReportErrorSummary("double-free", &stack);
+  ReportErrorSummary(scariness.GetDescription(), &stack);
 }
 
 void ErrorNewDeleteSizeMismatch::Print() {
@@ -111,9 +111,9 @@ void ErrorNewDeleteSizeMismatch::Print() {
   Printf("%s", d.Warning());
   char tname[128];
   Report(
-      "ERROR: AddressSanitizer: new-delete-type-mismatch on %p in thread "
+      "ERROR: AddressSanitizer: %s on %p in thread "
       "T%d%s:\n",
-      addr_description.addr, tid,
+      scariness.GetDescription(), addr_description.addr, tid,
       ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
   Printf("%s  object passed to delete has wrong type:\n", d.EndWarning());
   Printf(
@@ -125,7 +125,7 @@ void ErrorNewDeleteSizeMismatch::Print() {
   GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
   stack.Print();
   addr_description.Print();
-  ReportErrorSummary("new-delete-type-mismatch", &stack);
+  ReportErrorSummary(scariness.GetDescription(), &stack);
   Report(
       "HINT: if you don't care about these errors you may set "
       "ASAN_OPTIONS=new_delete_type_mismatch=0\n");
@@ -146,7 +146,7 @@ void ErrorFreeNotMalloced::Print() {
   GET_STACK_TRACE_FATAL(free_stack->trace[0], free_stack->top_frame_bp);
   stack.Print();
   addr_description.Print();
-  ReportErrorSummary("bad-free", &stack);
+  ReportErrorSummary(scariness.GetDescription(), &stack);
 }
 
 void ErrorAllocTypeMismatch::Print() {
@@ -157,7 +157,8 @@ void ErrorAllocTypeMismatch::Print() {
   CHECK_NE(alloc_type, dealloc_type);
   Decorator d;
   Printf("%s", d.Warning());
-  Report("ERROR: AddressSanitizer: alloc-dealloc-mismatch (%s vs %s) on %p\n",
+  Report("ERROR: AddressSanitizer: %s (%s vs %s) on %p\n",
+         scariness.GetDescription(),
          alloc_names[alloc_type], dealloc_names[dealloc_type],
          addr_description.addr);
   Printf("%s", d.EndWarning());
@@ -166,7 +167,7 @@ void ErrorAllocTypeMismatch::Print() {
   GET_STACK_TRACE_FATAL(dealloc_stack->trace[0], dealloc_stack->top_frame_bp);
   stack.Print();
   addr_description.Print();
-  ReportErrorSummary("alloc-dealloc-mismatch", &stack);
+  ReportErrorSummary(scariness.GetDescription(), &stack);
   Report(
       "HINT: if you don't care about these errors you may set "
       "ASAN_OPTIONS=alloc_dealloc_mismatch=0\n");
@@ -182,7 +183,7 @@ void ErrorMallocUsableSizeNotOwned::Print() {
   Printf("%s", d.EndWarning());
   stack->Print();
   addr_description.Print();
-  ReportErrorSummary("bad-malloc_usable_size", stack);
+  ReportErrorSummary(scariness.GetDescription(), stack);
 }
 
 void ErrorSanitizerGetAllocatedSizeNotOwned::Print() {
@@ -195,7 +196,7 @@ void ErrorSanitizerGetAllocatedSizeNotOwned::Print() {
   Printf("%s", d.EndWarning());
   stack->Print();
   addr_description.Print();
-  ReportErrorSummary("bad-__sanitizer_get_allocated_size", stack);
+  ReportErrorSummary(scariness.GetDescription(), stack);
 }
 
 void ErrorStringFunctionMemoryRangesOverlap::Print() {
@@ -220,13 +221,13 @@ void ErrorStringFunctionMemoryRangesOverlap::Print() {
 void ErrorStringFunctionSizeOverflow::Print() {
   Decorator d;
   Printf("%s", d.Warning());
-  const char *bug_type = "negative-size-param";
-  Report("ERROR: AddressSanitizer: %s: (size=%zd)\n", bug_type, size);
+  Report("ERROR: AddressSanitizer: %s: (size=%zd)\n",
+         scariness.GetDescription(), size);
   Printf("%s", d.EndWarning());
   scariness.Print();
   stack->Print();
   addr_description.Print();
-  ReportErrorSummary(bug_type, stack);
+  ReportErrorSummary(scariness.GetDescription(), stack);
 }
 
 void ErrorBadParamsToAnnotateContiguousContainer::Print() {
@@ -242,13 +243,14 @@ void ErrorBadParamsToAnnotateContiguousContainer::Print() {
   if (!IsAligned(beg, granularity))
     Report("ERROR: beg is not aligned by %d\n", granularity);
   stack->Print();
-  ReportErrorSummary("bad-__sanitizer_annotate_contiguous_container", stack);
+  ReportErrorSummary(scariness.GetDescription(), stack);
 }
 
 void ErrorODRViolation::Print() {
   Decorator d;
   Printf("%s", d.Warning());
-  Report("ERROR: AddressSanitizer: odr-violation (%p):\n", global1.beg);
+  Report("ERROR: AddressSanitizer: %s (%p):\n", scariness.GetDescription(),
+         global1.beg);
   Printf("%s", d.EndWarning());
   InternalScopedString g1_loc(256), g2_loc(256);
   PrintGlobalLocation(&g1_loc, global1);
@@ -268,23 +270,22 @@ void ErrorODRViolation::Print() {
       "HINT: if you don't care about these errors you may set "
       "ASAN_OPTIONS=detect_odr_violation=0\n");
   InternalScopedString error_msg(256);
-  error_msg.append("odr-violation: global '%s' at %s",
+  error_msg.append("%s: global '%s' at %s", scariness.GetDescription(),
                    MaybeDemangleGlobalName(global1.name), g1_loc.data());
   ReportErrorSummary(error_msg.data());
 }
 
 void ErrorInvalidPointerPair::Print() {
-  const char *bug_type = "invalid-pointer-pair";
   Decorator d;
   Printf("%s", d.Warning());
-  Report("ERROR: AddressSanitizer: invalid-pointer-pair: %p %p\n",
+  Report("ERROR: AddressSanitizer: %s: %p %p\n", scariness.GetDescription(),
          addr1_description.Address(), addr2_description.Address());
   Printf("%s", d.EndWarning());
   GET_STACK_TRACE_FATAL(pc, bp);
   stack.Print();
   addr1_description.Print();
   addr2_description.Print();
-  ReportErrorSummary(bug_type, &stack);
+  ReportErrorSummary(scariness.GetDescription(), &stack);
 }
 
 static bool AdjacentShadowValuesAreFullyPoisoned(u8 *s) {
index cfd58ab..9a12492 100644 (file)
@@ -172,6 +172,7 @@ struct ErrorMallocUsableSizeNotOwned : ErrorBase {
         stack(stack_),
         addr_description(addr, /*shouldLockThreadRegistry=*/false) {
     scariness.Clear();
+    scariness.Scare(10, "bad-malloc_usable_size");
   }
   void Print();
 };
@@ -189,6 +190,7 @@ struct ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
         stack(stack_),
         addr_description(addr, /*shouldLockThreadRegistry=*/false) {
     scariness.Clear();
+    scariness.Scare(10, "bad-__sanitizer_get_allocated_size");
   }
   void Print();
 };
@@ -258,7 +260,10 @@ struct ErrorBadParamsToAnnotateContiguousContainer : ErrorBase {
         beg(beg_),
         end(end_),
         old_mid(old_mid_),
-        new_mid(new_mid_) {}
+        new_mid(new_mid_) {
+    scariness.Clear();
+    scariness.Scare(10, "bad-__sanitizer_annotate_contiguous_container");
+  }
   void Print();
 };
 
@@ -274,7 +279,10 @@ struct ErrorODRViolation : ErrorBase {
         global1(*g1),
         global2(*g2),
         stack_id1(stack_id1_),
-        stack_id2(stack_id2_) {}
+        stack_id2(stack_id2_) {
+    scariness.Clear();
+    scariness.Scare(10, "odr-violation");
+  }
   void Print();
 };
 
@@ -292,7 +300,10 @@ struct ErrorInvalidPointerPair : ErrorBase {
         bp(bp_),
         sp(sp_),
         addr1_description(p1, 1, /*shouldLockThreadRegistry=*/false),
-        addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false) {}
+        addr2_description(p2, 1, /*shouldLockThreadRegistry=*/false)  {
+    scariness.Clear();
+    scariness.Scare(10, "invalid-pointer-pair");
+  }
   void Print();
 };
 
@@ -350,6 +361,7 @@ struct ErrorDescription {
   // We can add a wrapper around it to make it "more c++-like", but that would
   // add a lot of code and the benefit wouldn't be that big.
   union {
+    ErrorBase Base;
     ASAN_FOR_EACH_ERROR_KIND(ASAN_ERROR_DESCRIPTION_MEMBER)
   };
 
index 9748634..937ba40 100644 (file)
@@ -427,7 +427,7 @@ void __asan_describe_address(uptr addr) {
 }
 
 int __asan_report_present() {
-  return ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric;
+  return ScopedInErrorReport::CurrentError().kind != kErrorKindInvalid;
 }
 
 uptr __asan_get_report_pc() {
@@ -449,9 +449,11 @@ uptr __asan_get_report_sp() {
 }
 
 uptr __asan_get_report_address() {
-  if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
-    return ScopedInErrorReport::CurrentError()
-        .Generic.addr_description.Address();
+  ErrorDescription &err = ScopedInErrorReport::CurrentError();
+  if (err.kind == kErrorKindGeneric)
+    return err.Generic.addr_description.Address();
+  else if (err.kind == kErrorKindDoubleFree)
+    return err.DoubleFree.addr_description.addr;
   return 0;
 }
 
@@ -470,7 +472,7 @@ uptr __asan_get_report_access_size() {
 const char *__asan_get_report_description() {
   if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
     return ScopedInErrorReport::CurrentError().Generic.bug_descr;
-  return nullptr;
+  return ScopedInErrorReport::CurrentError().Base.scariness.GetDescription();
 }
 
 extern "C" {
diff --git a/compiler-rt/test/asan/TestCases/debug_double_free.cc b/compiler-rt/test/asan/TestCases/debug_double_free.cc
new file mode 100644 (file)
index 0000000..22081c3
--- /dev/null
@@ -0,0 +1,32 @@
+// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+
+#include <sanitizer/asan_interface.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+char *heap_ptr;
+
+int main() {
+  heap_ptr = (char *)malloc(10);
+  fprintf(stderr, "heap_ptr: %p\n", heap_ptr);
+  // CHECK: heap_ptr: 0x[[ADDR:[0-9a-f]+]]
+
+  free(heap_ptr);
+  free(heap_ptr);  // BOOM
+  return 0;
+}
+
+void __asan_on_error() {
+  int present = __asan_report_present();
+  void *addr = __asan_get_report_address();
+  const char *description = __asan_get_report_description();
+
+  fprintf(stderr, "%s\n", (present == 1) ? "report present" : "");
+  // CHECK: report present
+  fprintf(stderr, "addr: %p\n", addr);
+  // CHECK: addr: {{0x0*}}[[ADDR]]
+  fprintf(stderr, "description: %s\n", description);
+  // CHECK: description: double-free
+}
+
+// CHECK: AddressSanitizer: attempting double-free on {{0x0*}}[[ADDR]] in thread T0