[compiler-rt] r282107 - [asan] Reify ErrorGeneric

Filipe Cabecinhas via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 21 13:18:18 PDT 2016


Author: filcab
Date: Wed Sep 21 15:18:18 2016
New Revision: 282107

URL: http://llvm.org/viewvc/llvm-project?rev=282107&view=rev
Log:
[asan] Reify ErrorGeneric

Summary:
Finish work on PR30351 (last one, after D24551, D24552, and D24554 land)

Also replace the old ReportData structure/variable with the current_error_ static
member of the ScopedInErrorReport class.

This has the following side-effects:
  - Move ASAN_ON_ERROR(); call to the start of the destructor, instead
    of in StartReporting().
      - We only generate the error structure after the
        ScopedInErrorReport constructor finishes, so we can't call
        ASAN_ON_ERROR() during the constructor. I think this makes more
        sense, since we end up never running two of the ASAN_ON_ERROR()
        callback. This also works the same way as error reporting, since
        we end up having a lock around it. Otherwise we could end up
        with the ASAN_ON_ERROR() call for error 1, then the
        ASAN_ON_ERROR() call for error 2, and then lock the mutex for
        reporting error 1.
  - The __asan_get_report_* functions will be able to, in the future,
    provide information about other errors that aren't a "generic
    error". But we might want to rethink that API, since it's too
    restricted. Ideally we teach lldb about the current_error_ member of
    ScopedInErrorReport.

Reviewers: vitalybuka, kcc, eugenis

Subscribers: kubabrecka, llvm-commits

Differential Revision: https://reviews.llvm.org/D24555

Modified:
    compiler-rt/trunk/lib/asan/asan_descriptions.h
    compiler-rt/trunk/lib/asan/asan_errors.cc
    compiler-rt/trunk/lib/asan/asan_errors.h
    compiler-rt/trunk/lib/asan/asan_report.cc

Modified: compiler-rt/trunk/lib/asan/asan_descriptions.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_descriptions.h?rev=282107&r1=282106&r2=282107&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_descriptions.h (original)
+++ compiler-rt/trunk/lib/asan/asan_descriptions.h Wed Sep 21 15:18:18 2016
@@ -214,7 +214,7 @@ class AddressDescription {
     }
     UNREACHABLE("AddressInformation kind is invalid");
   }
-  void Print() const {
+  void Print(const char *bug_descr = nullptr) const {
     switch (data.kind) {
       case kAddressKindWild:
         Printf("Address %p is a wild pointer.\n", data.addr);
@@ -226,7 +226,8 @@ class AddressDescription {
       case kAddressKindStack:
         return data.stack.Print();
       case kAddressKindGlobal:
-        return data.global.Print();
+        // initialization-order-fiasco has a special Print()
+        return data.global.Print(bug_descr);
     }
     UNREACHABLE("AddressInformation kind is invalid");
   }

Modified: compiler-rt/trunk/lib/asan/asan_errors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_errors.cc?rev=282107&r1=282106&r2=282107&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_errors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_errors.cc Wed Sep 21 15:18:18 2016
@@ -281,4 +281,216 @@ void ErrorInvalidPointerPair::Print() {
   ReportErrorSummary(bug_type, &stack);
 }
 
+static bool AdjacentShadowValuesAreFullyPoisoned(u8 *s) {
+  return s[-1] > 127 && s[1] > 127;
+}
+
+ErrorGeneric::ErrorGeneric(u32 tid, uptr pc_, uptr bp_, uptr sp_, uptr addr,
+                           bool is_write_, uptr access_size_)
+    : ErrorBase(tid),
+      addr_description(addr, access_size_, /*shouldLockThreadRegistry=*/false),
+      pc(pc_),
+      bp(bp_),
+      sp(sp_),
+      access_size(access_size_),
+      is_write(is_write_),
+      shadow_val(0) {
+  scariness.Clear();
+  if (access_size) {
+    if (access_size <= 9) {
+      char desr[] = "?-byte";
+      desr[0] = '0' + access_size;
+      scariness.Scare(access_size + access_size / 2, desr);
+    } else if (access_size >= 10) {
+      scariness.Scare(15, "multi-byte");
+    }
+    is_write ? scariness.Scare(20, "write") : scariness.Scare(1, "read");
+
+    // Determine the error type.
+    bug_descr = "unknown-crash";
+    if (AddrIsInMem(addr)) {
+      u8 *shadow_addr = (u8 *)MemToShadow(addr);
+      // If we are accessing 16 bytes, look at the second shadow byte.
+      if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY) shadow_addr++;
+      // If we are in the partial right redzone, look at the next shadow byte.
+      if (*shadow_addr > 0 && *shadow_addr < 128) shadow_addr++;
+      bool far_from_bounds = false;
+      shadow_val = *shadow_addr;
+      int bug_type_score = 0;
+      // For use-after-frees reads are almost as bad as writes.
+      int read_after_free_bonus = 0;
+      switch (shadow_val) {
+        case kAsanHeapLeftRedzoneMagic:
+        case kAsanArrayCookieMagic:
+          bug_descr = "heap-buffer-overflow";
+          bug_type_score = 10;
+          far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
+          break;
+        case kAsanHeapFreeMagic:
+          bug_descr = "heap-use-after-free";
+          bug_type_score = 20;
+          if (!is_write) read_after_free_bonus = 18;
+          break;
+        case kAsanStackLeftRedzoneMagic:
+          bug_descr = "stack-buffer-underflow";
+          bug_type_score = 25;
+          far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
+          break;
+        case kAsanInitializationOrderMagic:
+          bug_descr = "initialization-order-fiasco";
+          bug_type_score = 1;
+          break;
+        case kAsanStackMidRedzoneMagic:
+        case kAsanStackRightRedzoneMagic:
+          bug_descr = "stack-buffer-overflow";
+          bug_type_score = 25;
+          far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
+          break;
+        case kAsanStackAfterReturnMagic:
+          bug_descr = "stack-use-after-return";
+          bug_type_score = 30;
+          if (!is_write) read_after_free_bonus = 18;
+          break;
+        case kAsanUserPoisonedMemoryMagic:
+          bug_descr = "use-after-poison";
+          bug_type_score = 20;
+          break;
+        case kAsanContiguousContainerOOBMagic:
+          bug_descr = "container-overflow";
+          bug_type_score = 10;
+          break;
+        case kAsanStackUseAfterScopeMagic:
+          bug_descr = "stack-use-after-scope";
+          bug_type_score = 10;
+          break;
+        case kAsanGlobalRedzoneMagic:
+          bug_descr = "global-buffer-overflow";
+          bug_type_score = 10;
+          far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
+          break;
+        case kAsanIntraObjectRedzone:
+          bug_descr = "intra-object-overflow";
+          bug_type_score = 10;
+          break;
+        case kAsanAllocaLeftMagic:
+        case kAsanAllocaRightMagic:
+          bug_descr = "dynamic-stack-buffer-overflow";
+          bug_type_score = 25;
+          far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
+          break;
+      }
+      scariness.Scare(bug_type_score + read_after_free_bonus, bug_descr);
+      if (far_from_bounds) scariness.Scare(10, "far-from-bounds");
+    }
+  }
+}
+
+static void PrintContainerOverflowHint() {
+  Printf("HINT: if you don't care about these errors you may set "
+         "ASAN_OPTIONS=detect_container_overflow=0.\n"
+         "If you suspect a false positive see also: "
+         "https://github.com/google/sanitizers/wiki/"
+         "AddressSanitizerContainerOverflow.\n");
+}
+
+static void PrintShadowByte(InternalScopedString *str, const char *before,
+    u8 byte, const char *after = "\n") {
+  PrintMemoryByte(str, before, byte, /*in_shadow*/true, after);
+}
+
+static void PrintLegend(InternalScopedString *str) {
+  str->append(
+      "Shadow byte legend (one shadow byte represents %d "
+      "application bytes):\n",
+      (int)SHADOW_GRANULARITY);
+  PrintShadowByte(str, "  Addressable:           ", 0);
+  str->append("  Partially addressable: ");
+  for (u8 i = 1; i < SHADOW_GRANULARITY; i++) PrintShadowByte(str, "", i, " ");
+  str->append("\n");
+  PrintShadowByte(str, "  Heap left redzone:       ",
+                  kAsanHeapLeftRedzoneMagic);
+  PrintShadowByte(str, "  Freed heap region:       ", kAsanHeapFreeMagic);
+  PrintShadowByte(str, "  Stack left redzone:      ",
+                  kAsanStackLeftRedzoneMagic);
+  PrintShadowByte(str, "  Stack mid redzone:       ",
+                  kAsanStackMidRedzoneMagic);
+  PrintShadowByte(str, "  Stack right redzone:     ",
+                  kAsanStackRightRedzoneMagic);
+  PrintShadowByte(str, "  Stack after return:      ",
+                  kAsanStackAfterReturnMagic);
+  PrintShadowByte(str, "  Stack use after scope:   ",
+                  kAsanStackUseAfterScopeMagic);
+  PrintShadowByte(str, "  Global redzone:          ", kAsanGlobalRedzoneMagic);
+  PrintShadowByte(str, "  Global init order:       ",
+                  kAsanInitializationOrderMagic);
+  PrintShadowByte(str, "  Poisoned by user:        ",
+                  kAsanUserPoisonedMemoryMagic);
+  PrintShadowByte(str, "  Container overflow:      ",
+                  kAsanContiguousContainerOOBMagic);
+  PrintShadowByte(str, "  Array cookie:            ",
+                  kAsanArrayCookieMagic);
+  PrintShadowByte(str, "  Intra object redzone:    ",
+                  kAsanIntraObjectRedzone);
+  PrintShadowByte(str, "  ASan internal:           ", kAsanInternalHeapMagic);
+  PrintShadowByte(str, "  Left alloca redzone:     ", kAsanAllocaLeftMagic);
+  PrintShadowByte(str, "  Right alloca redzone:    ", kAsanAllocaRightMagic);
+}
+
+static void PrintShadowBytes(InternalScopedString *str, const char *before,
+                             u8 *bytes, u8 *guilty, uptr n) {
+  Decorator d;
+  if (before) str->append("%s%p:", before, bytes);
+  for (uptr i = 0; i < n; i++) {
+    u8 *p = bytes + i;
+    const char *before =
+        p == guilty ? "[" : (p - 1 == guilty && i != 0) ? "" : " ";
+    const char *after = p == guilty ? "]" : "";
+    PrintShadowByte(str, before, *p, after);
+  }
+  str->append("\n");
+}
+
+static void PrintShadowMemoryForAddress(uptr addr) {
+  if (!AddrIsInMem(addr)) return;
+  uptr shadow_addr = MemToShadow(addr);
+  const uptr n_bytes_per_row = 16;
+  uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
+  InternalScopedString str(4096 * 8);
+  str.append("Shadow bytes around the buggy address:\n");
+  for (int i = -5; i <= 5; i++) {
+    const char *prefix = (i == 0) ? "=>" : "  ";
+    PrintShadowBytes(&str, prefix, (u8 *)(aligned_shadow + i * n_bytes_per_row),
+                     (u8 *)shadow_addr, n_bytes_per_row);
+  }
+  if (flags()->print_legend) PrintLegend(&str);
+  Printf("%s", str.data());
+}
+
+void ErrorGeneric::Print() {
+  Decorator d;
+  Printf("%s", d.Warning());
+  uptr addr = addr_description.Address();
+  Report("ERROR: AddressSanitizer: %s on address %p at pc %p bp %p sp %p\n",
+         bug_descr, (void *)addr, pc, bp, sp);
+  Printf("%s", d.EndWarning());
+
+  char tname[128];
+  Printf("%s%s of size %zu at %p thread T%d%s%s\n", d.Access(),
+         access_size ? (is_write ? "WRITE" : "READ") : "ACCESS", access_size,
+         (void *)addr, tid,
+         ThreadNameWithParenthesis(tid, tname, sizeof(tname)), d.EndAccess());
+
+  scariness.Print();
+  GET_STACK_TRACE_FATAL(pc, bp);
+  stack.Print();
+
+  // Pass bug_descr because we have a special case for
+  // initialization-order-fiasco
+  addr_description.Print(bug_descr);
+  if (shadow_val == kAsanContiguousContainerOOBMagic)
+    PrintContainerOverflowHint();
+  ReportErrorSummary(bug_descr, &stack);
+  PrintShadowMemoryForAddress(addr);
+}
+
 }  // namespace __asan

Modified: compiler-rt/trunk/lib/asan/asan_errors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_errors.h?rev=282107&r1=282106&r2=282107&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_errors.h (original)
+++ compiler-rt/trunk/lib/asan/asan_errors.h Wed Sep 21 15:18:18 2016
@@ -296,6 +296,21 @@ struct ErrorInvalidPointerPair : ErrorBa
   void Print();
 };
 
+struct ErrorGeneric : ErrorBase {
+  AddressDescription addr_description;
+  uptr pc, bp, sp;
+  uptr access_size;
+  const char *bug_descr;
+  bool is_write;
+  u8 shadow_val;
+  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
+  // constructor
+  ErrorGeneric() = default;
+  ErrorGeneric(u32 tid, uptr addr, uptr pc_, uptr bp_, uptr sp_, bool is_write_,
+               uptr access_size_);
+  void Print();
+};
+
 // clang-format off
 #define ASAN_FOR_EACH_ERROR_KIND(macro)         \
   macro(StackOverflow)                          \
@@ -310,7 +325,8 @@ struct ErrorInvalidPointerPair : ErrorBa
   macro(StringFunctionSizeOverflow)             \
   macro(BadParamsToAnnotateContiguousContainer) \
   macro(ODRViolation)                           \
-  macro(InvalidPointerPair)
+  macro(InvalidPointerPair)                     \
+  macro(Generic)
 // clang-format on
 
 #define ASAN_DEFINE_ERROR_KIND(name) kErrorKind##name,

Modified: compiler-rt/trunk/lib/asan/asan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.cc?rev=282107&r1=282106&r2=282107&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Wed Sep 21 15:18:18 2016
@@ -37,19 +37,6 @@ static BlockingMutex error_message_buf_m
 static const unsigned kAsanBuggyPcPoolSize = 25;
 static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize];
 
-struct ReportData {
-  uptr pc;
-  uptr sp;
-  uptr bp;
-  uptr addr;
-  bool is_write;
-  uptr access_size;
-  const char *description;
-};
-
-static bool report_happened = false;
-static ReportData report_data = {};
-
 void AppendToErrorMessageBuffer(const char *buffer) {
   BlockingMutexLock l(&error_message_buf_mutex);
   if (!error_message_buffer) {
@@ -78,79 +65,6 @@ void PrintMemoryByte(InternalScopedStrin
               in_shadow ? d.EndShadowByte() : d.EndMemoryByte(), after);
 }
 
-static void PrintShadowByte(InternalScopedString *str, const char *before,
-    u8 byte, const char *after = "\n") {
-  PrintMemoryByte(str, before, byte, /*in_shadow*/true, after);
-}
-
-static void PrintShadowBytes(InternalScopedString *str, const char *before,
-                             u8 *bytes, u8 *guilty, uptr n) {
-  Decorator d;
-  if (before) str->append("%s%p:", before, bytes);
-  for (uptr i = 0; i < n; i++) {
-    u8 *p = bytes + i;
-    const char *before =
-        p == guilty ? "[" : (p - 1 == guilty && i != 0) ? "" : " ";
-    const char *after = p == guilty ? "]" : "";
-    PrintShadowByte(str, before, *p, after);
-  }
-  str->append("\n");
-}
-
-static void PrintLegend(InternalScopedString *str) {
-  str->append(
-      "Shadow byte legend (one shadow byte represents %d "
-      "application bytes):\n",
-      (int)SHADOW_GRANULARITY);
-  PrintShadowByte(str, "  Addressable:           ", 0);
-  str->append("  Partially addressable: ");
-  for (u8 i = 1; i < SHADOW_GRANULARITY; i++) PrintShadowByte(str, "", i, " ");
-  str->append("\n");
-  PrintShadowByte(str, "  Heap left redzone:       ",
-                  kAsanHeapLeftRedzoneMagic);
-  PrintShadowByte(str, "  Freed heap region:       ", kAsanHeapFreeMagic);
-  PrintShadowByte(str, "  Stack left redzone:      ",
-                  kAsanStackLeftRedzoneMagic);
-  PrintShadowByte(str, "  Stack mid redzone:       ",
-                  kAsanStackMidRedzoneMagic);
-  PrintShadowByte(str, "  Stack right redzone:     ",
-                  kAsanStackRightRedzoneMagic);
-  PrintShadowByte(str, "  Stack after return:      ",
-                  kAsanStackAfterReturnMagic);
-  PrintShadowByte(str, "  Stack use after scope:   ",
-                  kAsanStackUseAfterScopeMagic);
-  PrintShadowByte(str, "  Global redzone:          ", kAsanGlobalRedzoneMagic);
-  PrintShadowByte(str, "  Global init order:       ",
-                  kAsanInitializationOrderMagic);
-  PrintShadowByte(str, "  Poisoned by user:        ",
-                  kAsanUserPoisonedMemoryMagic);
-  PrintShadowByte(str, "  Container overflow:      ",
-                  kAsanContiguousContainerOOBMagic);
-  PrintShadowByte(str, "  Array cookie:            ",
-                  kAsanArrayCookieMagic);
-  PrintShadowByte(str, "  Intra object redzone:    ",
-                  kAsanIntraObjectRedzone);
-  PrintShadowByte(str, "  ASan internal:           ", kAsanInternalHeapMagic);
-  PrintShadowByte(str, "  Left alloca redzone:     ", kAsanAllocaLeftMagic);
-  PrintShadowByte(str, "  Right alloca redzone:    ", kAsanAllocaRightMagic);
-}
-
-static void PrintShadowMemoryForAddress(uptr addr) {
-  if (!AddrIsInMem(addr)) return;
-  uptr shadow_addr = MemToShadow(addr);
-  const uptr n_bytes_per_row = 16;
-  uptr aligned_shadow = shadow_addr & ~(n_bytes_per_row - 1);
-  InternalScopedString str(4096 * 8);
-  str.append("Shadow bytes around the buggy address:\n");
-  for (int i = -5; i <= 5; i++) {
-    const char *prefix = (i == 0) ? "=>" : "  ";
-    PrintShadowBytes(&str, prefix, (u8 *)(aligned_shadow + i * n_bytes_per_row),
-                     (u8 *)shadow_addr, n_bytes_per_row);
-  }
-  if (flags()->print_legend) PrintLegend(&str);
-  Printf("%s", str.data());
-}
-
 static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
                                 const char *zone_name) {
   if (zone_ptr) {
@@ -201,12 +115,11 @@ bool ParseFrameDescription(const char *f
 // immediately after printing error report.
 class ScopedInErrorReport {
  public:
-  explicit ScopedInErrorReport(ReportData *report = nullptr,
-                               bool fatal = false) {
+  explicit ScopedInErrorReport(bool fatal = false) {
     halt_on_error_ = fatal || flags()->halt_on_error;
 
     if (lock_.TryLock()) {
-      StartReporting(report);
+      StartReporting();
       return;
     }
 
@@ -248,10 +161,11 @@ class ScopedInErrorReport {
       lock_.Lock();
     }
 
-    StartReporting(report);
+    StartReporting();
   }
 
   ~ScopedInErrorReport() {
+    ASAN_ON_ERROR();
     if (current_error_.IsValid()) current_error_.Print();
 
     // Make sure the current thread is announced.
@@ -279,6 +193,12 @@ class ScopedInErrorReport {
     if (error_report_callback) {
       error_report_callback(buffer_copy.data());
     }
+
+    // In halt_on_error = false mode, reset the current error object (before
+    // unlocking).
+    if (!halt_on_error_)
+      internal_memset(&current_error_, 0, sizeof(current_error_));
+
     CommonSanitizerReportMutex.Unlock();
     reporting_thread_tid_ = kInvalidTid;
     lock_.Unlock();
@@ -294,11 +214,12 @@ class ScopedInErrorReport {
     current_error_ = description;
   }
 
+  static ErrorDescription &CurrentError() {
+    return current_error_;
+  }
+
  private:
-  void StartReporting(ReportData *report) {
-    if (report) report_data = *report;
-    report_happened = true;
-    ASAN_ON_ERROR();
+  void StartReporting() {
     // Make sure the registry and sanitizer report mutexes are locked while
     // we're printing an error report.
     // We can lock them only here to avoid self-deadlock in case of
@@ -323,13 +244,13 @@ u32 ScopedInErrorReport::reporting_threa
 ErrorDescription ScopedInErrorReport::current_error_;
 
 void ReportStackOverflow(const SignalContext &sig) {
-  ScopedInErrorReport in_report(/*report*/ nullptr, /*fatal*/ true);
+  ScopedInErrorReport in_report(/*fatal*/ true);
   ErrorStackOverflow error(GetCurrentTidOrInvalid(), sig);
   in_report.ReportError(error);
 }
 
 void ReportDeadlySignal(int signo, const SignalContext &sig) {
-  ScopedInErrorReport in_report(/*report*/ nullptr, /*fatal*/ true);
+  ScopedInErrorReport in_report(/*fatal*/ true);
   ErrorDeadlySignal error(GetCurrentTidOrInvalid(), sig, signo);
   in_report.ReportError(error);
 }
@@ -461,34 +382,10 @@ static bool SuppressErrorReport(uptr pc)
   Die();
 }
 
-static void PrintContainerOverflowHint() {
-  Printf("HINT: if you don't care about these errors you may set "
-         "ASAN_OPTIONS=detect_container_overflow=0.\n"
-         "If you suspect a false positive see also: "
-         "https://github.com/google/sanitizers/wiki/"
-         "AddressSanitizerContainerOverflow.\n");
-}
-
-static bool AdjacentShadowValuesAreFullyPoisoned(u8 *s) {
-  return s[-1] > 127 && s[1] > 127;
-}
-
 void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
                         uptr access_size, u32 exp, bool fatal) {
   if (!fatal && SuppressErrorReport(pc)) return;
   ENABLE_FRAME_POINTER;
-  ScarinessScore SS;
-
-  if (access_size) {
-    if (access_size <= 9) {
-      char desr[] = "?-byte";
-      desr[0] = '0' + access_size;
-      SS.Scare(access_size + access_size / 2, desr);
-    } else if (access_size >= 10) {
-      SS.Scare(15, "multi-byte");
-    }
-    is_write ? SS.Scare(20, "write") : SS.Scare(1, "read");
-  }
 
   // Optimization experiments.
   // The experiments can be used to evaluate potential optimizations that remove
@@ -499,116 +396,10 @@ void ReportGenericError(uptr pc, uptr bp
   // The reaction to a non-zero value of exp is to be defined.
   (void)exp;
 
-  // Determine the error type.
-  const char *bug_descr = "unknown-crash";
-  u8 shadow_val = 0;
-  if (AddrIsInMem(addr)) {
-    u8 *shadow_addr = (u8*)MemToShadow(addr);
-    // If we are accessing 16 bytes, look at the second shadow byte.
-    if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY)
-      shadow_addr++;
-    // If we are in the partial right redzone, look at the next shadow byte.
-    if (*shadow_addr > 0 && *shadow_addr < 128)
-      shadow_addr++;
-    bool far_from_bounds = false;
-    shadow_val = *shadow_addr;
-    int bug_type_score = 0;
-    // For use-after-frees reads are almost as bad as writes.
-    int read_after_free_bonus = 0;
-    switch (shadow_val) {
-      case kAsanHeapLeftRedzoneMagic:
-      case kAsanArrayCookieMagic:
-        bug_descr = "heap-buffer-overflow";
-        bug_type_score = 10;
-        far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
-        break;
-      case kAsanHeapFreeMagic:
-        bug_descr = "heap-use-after-free";
-        bug_type_score = 20;
-        if (!is_write) read_after_free_bonus = 18;
-        break;
-      case kAsanStackLeftRedzoneMagic:
-        bug_descr = "stack-buffer-underflow";
-        bug_type_score = 25;
-        far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
-        break;
-      case kAsanInitializationOrderMagic:
-        bug_descr = "initialization-order-fiasco";
-        bug_type_score = 1;
-        break;
-      case kAsanStackMidRedzoneMagic:
-      case kAsanStackRightRedzoneMagic:
-        bug_descr = "stack-buffer-overflow";
-        bug_type_score = 25;
-        far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
-        break;
-      case kAsanStackAfterReturnMagic:
-        bug_descr = "stack-use-after-return";
-        bug_type_score = 30;
-        if (!is_write) read_after_free_bonus = 18;
-        break;
-      case kAsanUserPoisonedMemoryMagic:
-        bug_descr = "use-after-poison";
-        bug_type_score = 20;
-        break;
-      case kAsanContiguousContainerOOBMagic:
-        bug_descr = "container-overflow";
-        bug_type_score = 10;
-        break;
-      case kAsanStackUseAfterScopeMagic:
-        bug_descr = "stack-use-after-scope";
-        bug_type_score = 10;
-        break;
-      case kAsanGlobalRedzoneMagic:
-        bug_descr = "global-buffer-overflow";
-        bug_type_score = 10;
-        far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
-        break;
-      case kAsanIntraObjectRedzone:
-        bug_descr = "intra-object-overflow";
-        bug_type_score = 10;
-        break;
-      case kAsanAllocaLeftMagic:
-      case kAsanAllocaRightMagic:
-        bug_descr = "dynamic-stack-buffer-overflow";
-        bug_type_score = 25;
-        far_from_bounds = AdjacentShadowValuesAreFullyPoisoned(shadow_addr);
-        break;
-    }
-    SS.Scare(bug_type_score + read_after_free_bonus, bug_descr);
-    if (far_from_bounds)
-      SS.Scare(10, "far-from-bounds");
-  }
-
-  ReportData report = { pc, sp, bp, addr, (bool)is_write, access_size,
-                        bug_descr };
-  ScopedInErrorReport in_report(&report, fatal);
-
-  Decorator d;
-  Printf("%s", d.Warning());
-  Report("ERROR: AddressSanitizer: %s on address "
-             "%p at pc %p bp %p sp %p\n",
-             bug_descr, (void*)addr, pc, bp, sp);
-  Printf("%s", d.EndWarning());
-
-  u32 curr_tid = GetCurrentTidOrInvalid();
-  char tname[128];
-  Printf("%s%s of size %zu at %p thread T%d%s%s\n",
-         d.Access(),
-         access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
-         access_size, (void*)addr, curr_tid,
-         ThreadNameWithParenthesis(curr_tid, tname, sizeof(tname)),
-         d.EndAccess());
-
-  SS.Print();
-  GET_STACK_TRACE_FATAL(pc, bp);
-  stack.Print();
-
-  PrintAddressDescription(addr, access_size, bug_descr);
-  if (shadow_val == kAsanContiguousContainerOOBMagic)
-    PrintContainerOverflowHint();
-  ReportErrorSummary(bug_descr, &stack);
-  PrintShadowMemoryForAddress(addr);
+  ScopedInErrorReport in_report(fatal);
+  ErrorGeneric error(GetCurrentTidOrInvalid(), pc, bp, sp, addr, is_write,
+                     access_size);
+  in_report.ReportError(error);
 }
 
 }  // namespace __asan
@@ -636,35 +427,50 @@ void __asan_describe_address(uptr addr)
 }
 
 int __asan_report_present() {
-  return report_happened ? 1 : 0;
+  return ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric;
 }
 
 uptr __asan_get_report_pc() {
-  return report_data.pc;
+  if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
+    return ScopedInErrorReport::CurrentError().Generic.pc;
+  return 0;
 }
 
 uptr __asan_get_report_bp() {
-  return report_data.bp;
+  if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
+    return ScopedInErrorReport::CurrentError().Generic.bp;
+  return 0;
 }
 
 uptr __asan_get_report_sp() {
-  return report_data.sp;
+  if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
+    return ScopedInErrorReport::CurrentError().Generic.sp;
+  return 0;
 }
 
 uptr __asan_get_report_address() {
-  return report_data.addr;
+  if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
+    return ScopedInErrorReport::CurrentError()
+        .Generic.addr_description.Address();
+  return 0;
 }
 
 int __asan_get_report_access_type() {
-  return report_data.is_write ? 1 : 0;
+  if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
+    return ScopedInErrorReport::CurrentError().Generic.is_write;
+  return 0;
 }
 
 uptr __asan_get_report_access_size() {
-  return report_data.access_size;
+  if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
+    return ScopedInErrorReport::CurrentError().Generic.access_size;
+  return 0;
 }
 
 const char *__asan_get_report_description() {
-  return report_data.description;
+  if (ScopedInErrorReport::CurrentError().kind == kErrorKindGeneric)
+    return ScopedInErrorReport::CurrentError().Generic.bug_descr;
+  return nullptr;
 }
 
 extern "C" {




More information about the llvm-commits mailing list