[compiler-rt] r252723 - [ASan] Enable optional ASan recovery.

Yury Gribov via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 11 03:59:39 PST 2015


Author: ygribov
Date: Wed Nov 11 05:59:38 2015
New Revision: 252723

URL: http://llvm.org/viewvc/llvm-project?rev=252723&view=rev
Log:
[ASan] Enable optional ASan recovery.

Differential Revision: http://reviews.llvm.org/D12318

Added:
    compiler-rt/trunk/test/asan/TestCases/Linux/halt_on_error-torture.cc
    compiler-rt/trunk/test/asan/TestCases/halt_on_error-1.c
Modified:
    compiler-rt/trunk/lib/asan/asan_flags.inc
    compiler-rt/trunk/lib/asan/asan_interceptors.cc
    compiler-rt/trunk/lib/asan/asan_interface_internal.h
    compiler-rt/trunk/lib/asan/asan_report.cc
    compiler-rt/trunk/lib/asan/asan_report.h
    compiler-rt/trunk/lib/asan/asan_rtl.cc
    compiler-rt/trunk/test/asan/TestCases/Darwin/interface_symbols_darwin.c
    compiler-rt/trunk/test/asan/TestCases/Linux/interface_symbols_linux.c

Modified: compiler-rt/trunk/lib/asan/asan_flags.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_flags.inc?rev=252723&r1=252722&r2=252723&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_flags.inc (original)
+++ compiler-rt/trunk/lib/asan/asan_flags.inc Wed Nov 11 05:59:38 2015
@@ -134,3 +134,6 @@ ASAN_FLAG(int, detect_odr_violation, 2,
 ASAN_FLAG(bool, dump_instruction_bytes, false,
           "If true, dump 16 bytes starting at the instruction that caused SEGV")
 ASAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
+ASAN_FLAG(bool, halt_on_error, true,
+          "Crash the program after printing the first error report "
+          "(WARNING: USE AT YOUR OWN RISK!)")

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=252723&r1=252722&r2=252723&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Wed Nov 11 05:59:38 2015
@@ -75,7 +75,7 @@ struct AsanInterceptorContext {
       }                                                                 \
       if (!suppressed) {                                                \
         GET_CURRENT_PC_BP_SP;                                           \
-        __asan_report_error(pc, bp, sp, __bad, isWrite, __size, 0);     \
+        ReportGenericError(pc, bp, sp, __bad, isWrite, __size, 0, false);\
       }                                                                 \
     }                                                                   \
   } while (0)

Modified: compiler-rt/trunk/lib/asan/asan_interface_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interface_internal.h?rev=252723&r1=252722&r2=252723&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interface_internal.h (original)
+++ compiler-rt/trunk/lib/asan/asan_interface_internal.h Wed Nov 11 05:59:38 2015
@@ -167,6 +167,19 @@ extern "C" {
   SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN(uptr p, uptr size);
   SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN(uptr p, uptr size);
 
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_load1_noabort(uptr p);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_load2_noabort(uptr p);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_load4_noabort(uptr p);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_load8_noabort(uptr p);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_load16_noabort(uptr p);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_store1_noabort(uptr p);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_store2_noabort(uptr p);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_store4_noabort(uptr p);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_store8_noabort(uptr p);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_store16_noabort(uptr p);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_loadN_noabort(uptr p, uptr size);
+  SANITIZER_INTERFACE_ATTRIBUTE void __asan_storeN_noabort(uptr p, uptr size);
+
   SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load1(uptr p, u32 exp);
   SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load2(uptr p, u32 exp);
   SANITIZER_INTERFACE_ATTRIBUTE void __asan_exp_load4(uptr p, u32 exp);

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=252723&r1=252722&r2=252723&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Wed Nov 11 05:59:38 2015
@@ -622,41 +622,56 @@ void DescribeThread(AsanThreadContext *c
 // immediately after printing error report.
 class ScopedInErrorReport {
  public:
-  explicit ScopedInErrorReport(ReportData *report = nullptr) {
-    static atomic_uint32_t num_calls;
-    static u32 reporting_thread_tid;
-    if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) {
+  explicit ScopedInErrorReport(ReportData *report = nullptr,
+                               bool fatal = false) {
+    halt_on_error_ = fatal || flags()->halt_on_error;
+
+    if (lock_.TryLock()) {
+      StartReporting(report);
+      return;
+    }
+
+    // ASan found two bugs in different threads simultaneously.
+
+    u32 current_tid = GetCurrentTidOrInvalid();
+    if (current_tid == reporting_thread_tid_ || current_tid == kInvalidTid) {
+      // This is either asynch signal or nested error during error reporting.
+      // Fail fast to avoid deadlocks.
+
+      // Can't use Report() here because of potential deadlocks
+      // in nested signal handlers.
+      const char msg[] = "AddressSanitizer: nested bug in the same thread, "
+                         "aborting.\n";
+      WriteToFile(kStderrFd, msg, sizeof(msg));
+
+      internal__exit(common_flags()->exitcode);
+    }
+
+    if (halt_on_error_) {
       // Do not print more than one report, otherwise they will mix up.
       // Error reporting functions shouldn't return at this situation, as
-      // they are defined as no-return.
+      // they are effectively no-returns.
+
       Report("AddressSanitizer: while reporting a bug found another one. "
-                 "Ignoring.\n");
-      u32 current_tid = GetCurrentTidOrInvalid();
-      if (current_tid != reporting_thread_tid) {
-        // ASan found two bugs in different threads simultaneously. Sleep
-        // long enough to make sure that the thread which started to print
-        // an error report will finish doing it.
-        SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
-      }
+             "Ignoring.\n");
+
+      // Sleep long enough to make sure that the thread which started
+      // to print an error report will finish doing it.
+      SleepForSeconds(Max(100, flags()->sleep_before_dying + 1));
+
       // If we're still not dead for some reason, use raw _exit() instead of
       // Die() to bypass any additional checks.
       internal__exit(common_flags()->exitcode);
+    } else {
+      // The other thread will eventually finish reporting
+      // so it's safe to wait
+      lock_.Lock();
     }
-    if (report) report_data = *report;
-    report_happened = true;
-    ASAN_ON_ERROR();
-    // 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
-    // recursive reports.
-    asanThreadRegistry().Lock();
-    CommonSanitizerReportMutex.Lock();
-    reporting_thread_tid = GetCurrentTidOrInvalid();
-    Printf("===================================================="
-           "=============\n");
+
+    StartReporting(report);
   }
-  // Destructor is NORETURN, as functions that report errors are.
-  NORETURN ~ScopedInErrorReport() {
+
+  ~ScopedInErrorReport() {
     // Make sure the current thread is announced.
     DescribeThread(GetCurrentThread());
     // We may want to grab this lock again when printing stats.
@@ -667,11 +682,39 @@ class ScopedInErrorReport {
     if (error_report_callback) {
       error_report_callback(error_message_buffer);
     }
-    Report("ABORTING\n");
-    Die();
+    CommonSanitizerReportMutex.Unlock();
+    reporting_thread_tid_ = kInvalidTid;
+    lock_.Unlock();
+    if (halt_on_error_) {
+      Report("ABORTING\n");
+      Die();
+    }
   }
+
+ private:
+  void StartReporting(ReportData *report) {
+    if (report) report_data = *report;
+    report_happened = true;
+    ASAN_ON_ERROR();
+    // 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
+    // recursive reports.
+    asanThreadRegistry().Lock();
+    CommonSanitizerReportMutex.Lock();
+    reporting_thread_tid_ = GetCurrentTidOrInvalid();
+    Printf("===================================================="
+           "=============\n");
+  }
+
+  static StaticSpinMutex lock_;
+  static u32 reporting_thread_tid_;
+  bool halt_on_error_;
 };
 
+StaticSpinMutex ScopedInErrorReport::lock_;
+u32 ScopedInErrorReport::reporting_thread_tid_;
+
 void ReportStackOverflow(const SignalContext &sig) {
   ScopedInErrorReport in_report;
   Decorator d;
@@ -688,7 +731,7 @@ void ReportStackOverflow(const SignalCon
 }
 
 void ReportDeadlySignal(const char *description, const SignalContext &sig) {
-  ScopedInErrorReport in_report;
+  ScopedInErrorReport in_report(/*report*/nullptr, /*fatal*/true);
   Decorator d;
   Printf("%s", d.Warning());
   Report(
@@ -1034,7 +1077,7 @@ void __asan_report_error(uptr pc, uptr b
 
   ReportData report = { pc, sp, bp, addr, (bool)is_write, access_size,
                         bug_descr };
-  ScopedInErrorReport in_report(&report);
+  ScopedInErrorReport in_report(&report, fatal);
 
   Decorator d;
   Printf("%s", d.Warning());
@@ -1060,6 +1103,18 @@ void __asan_report_error(uptr pc, uptr b
   PrintShadowMemoryForAddress(addr);
 }
 
+}  // namespace __asan
+
+// --------------------------- Interface --------------------- {{{1
+using namespace __asan;  // NOLINT
+
+void __asan_report_error(uptr pc, uptr bp, uptr sp, uptr addr, int is_write,
+                         uptr access_size, u32 exp) {
+  ENABLE_FRAME_POINTER;
+  bool fatal = flags()->halt_on_error;
+  ReportGenericError(pc, bp, sp, addr, is_write, access_size, exp, fatal);
+}
+
 void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) {
   error_report_callback = callback;
   if (callback) {

Modified: compiler-rt/trunk/lib/asan/asan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.h?rev=252723&r1=252722&r2=252723&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.h (original)
+++ compiler-rt/trunk/lib/asan/asan_report.h Wed Nov 11 05:59:38 2015
@@ -49,45 +49,41 @@ bool DescribeAddressIfStack(uptr addr, u
 void DescribeThread(AsanThreadContext *context);
 
 // Different kinds of error reports.
-void NORETURN ReportStackOverflow(const SignalContext &sig);
-void NORETURN ReportDeadlySignal(const char* description,
-                                 const SignalContext &sig);
-void NORETURN ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size,
-                                          BufferedStackTrace *free_stack);
-void NORETURN ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack);
-void NORETURN ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack);
-void NORETURN ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
-                                      AllocType alloc_type,
-                                      AllocType dealloc_type);
-void NORETURN
-    ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack);
-void NORETURN
-    ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
-                                            BufferedStackTrace *stack);
-void NORETURN
-    ReportStringFunctionMemoryRangesOverlap(const char *function,
-                                            const char *offset1, uptr length1,
-                                            const char *offset2, uptr length2,
-                                            BufferedStackTrace *stack);
-void NORETURN ReportStringFunctionSizeOverflow(uptr offset, uptr size,
-                                               BufferedStackTrace *stack);
-void NORETURN
-    ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
-                                                 uptr old_mid, uptr new_mid,
-                                                 BufferedStackTrace *stack);
+void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
+                        uptr access_size, u32 exp, bool fatal);
+void ReportStackOverflow(const SignalContext &sig);
+void ReportDeadlySignal(const char *description, const SignalContext &sig);
+void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size,
+                                 BufferedStackTrace *free_stack);
+void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack);
+void ReportFreeNotMalloced(uptr addr, BufferedStackTrace *free_stack);
+void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
+                             AllocType alloc_type,
+                             AllocType dealloc_type);
+void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack);
+void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
+                                             BufferedStackTrace *stack);
+void ReportStringFunctionMemoryRangesOverlap(const char *function,
+                                             const char *offset1, uptr length1,
+                                             const char *offset2, uptr length2,
+                                             BufferedStackTrace *stack);
+void ReportStringFunctionSizeOverflow(uptr offset, uptr size,
+                                      BufferedStackTrace *stack);
+void ReportBadParamsToAnnotateContiguousContainer(uptr beg, uptr end,
+                                                  uptr old_mid, uptr new_mid,
+                                                  BufferedStackTrace *stack);
 
-void NORETURN
-ReportODRViolation(const __asan_global *g1, u32 stack_id1,
-                   const __asan_global *g2, u32 stack_id2);
+void ReportODRViolation(const __asan_global *g1, u32 stack_id1,
+                        const __asan_global *g2, u32 stack_id2);
 
 // Mac-specific errors and warnings.
 void WarnMacFreeUnallocated(uptr addr, uptr zone_ptr, const char *zone_name,
                             BufferedStackTrace *stack);
-void NORETURN ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr,
-                                        const char *zone_name,
-                                        BufferedStackTrace *stack);
-void NORETURN ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr,
-                                        const char *zone_name,
-                                        BufferedStackTrace *stack);
+void ReportMacMzReallocUnknown(uptr addr, uptr zone_ptr,
+                               const char *zone_name,
+                               BufferedStackTrace *stack);
+void ReportMacCfReallocUnknown(uptr addr, uptr zone_ptr,
+                               const char *zone_name,
+                               BufferedStackTrace *stack);
 
 }  // namespace __asan

Modified: compiler-rt/trunk/lib/asan/asan_rtl.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_rtl.cc?rev=252723&r1=252722&r2=252723&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_rtl.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_rtl.cc Wed Nov 11 05:59:38 2015
@@ -113,13 +113,18 @@ static void OnLowLevelAllocate(uptr ptr,
 extern "C" NOINLINE INTERFACE_ATTRIBUTE                             \
 void __asan_report_ ## type ## size(uptr addr) {                    \
   GET_CALLER_PC_BP_SP;                                              \
-  __asan_report_error(pc, bp, sp, addr, is_write, size, 0);         \
+  ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true);    \
 }                                                                   \
 extern "C" NOINLINE INTERFACE_ATTRIBUTE                             \
 void __asan_report_exp_ ## type ## size(uptr addr, u32 exp) {       \
   GET_CALLER_PC_BP_SP;                                              \
-  __asan_report_error(pc, bp, sp, addr, is_write, size, exp);       \
-}
+  ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true);  \
+}                                                                   \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE                             \
+void __asan_report_ ## type ## size ## _noabort(uptr addr) {        \
+  GET_CALLER_PC_BP_SP;                                              \
+  ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false);   \
+}                                                                   \
 
 ASAN_REPORT_ERROR(load, false, 1)
 ASAN_REPORT_ERROR(load, false, 2)
@@ -132,22 +137,27 @@ ASAN_REPORT_ERROR(store, true, 4)
 ASAN_REPORT_ERROR(store, true, 8)
 ASAN_REPORT_ERROR(store, true, 16)
 
-#define ASAN_REPORT_ERROR_N(type, is_write)                    \
-extern "C" NOINLINE INTERFACE_ATTRIBUTE                        \
-void __asan_report_ ## type ## _n(uptr addr, uptr size) {      \
-  GET_CALLER_PC_BP_SP;                                         \
-  __asan_report_error(pc, bp, sp, addr, is_write, size, 0);    \
-}                                                              \
-extern "C" NOINLINE INTERFACE_ATTRIBUTE                        \
+#define ASAN_REPORT_ERROR_N(type, is_write)                                 \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE                                     \
+void __asan_report_ ## type ## _n(uptr addr, uptr size) {                   \
+  GET_CALLER_PC_BP_SP;                                                      \
+  ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true);            \
+}                                                                           \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE                                     \
 void __asan_report_exp_ ## type ## _n(uptr addr, uptr size, u32 exp) {      \
   GET_CALLER_PC_BP_SP;                                                      \
-  __asan_report_error(pc, bp, sp, addr, is_write, size, exp);               \
-}
+  ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true);          \
+}                                                                           \
+extern "C" NOINLINE INTERFACE_ATTRIBUTE                                     \
+void __asan_report_ ## type ## _n_noabort(uptr addr, uptr size) {           \
+  GET_CALLER_PC_BP_SP;                                                      \
+  ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false);           \
+}                                                                           \
 
 ASAN_REPORT_ERROR_N(load, false)
 ASAN_REPORT_ERROR_N(store, true)
 
-#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg)        \
+#define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg, fatal) \
     uptr sp = MEM_TO_SHADOW(addr);                                             \
     uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp)          \
                                         : *reinterpret_cast<u16 *>(sp);        \
@@ -159,7 +169,8 @@ ASAN_REPORT_ERROR_N(store, true)
           *__asan_test_only_reported_buggy_pointer = addr;                     \
         } else {                                                               \
           GET_CALLER_PC_BP_SP;                                                 \
-          __asan_report_error(pc, bp, sp, addr, is_write, size, exp_arg);      \
+          ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg,        \
+                              fatal);                                          \
         }                                                                      \
       }                                                                        \
     }
@@ -167,12 +178,16 @@ ASAN_REPORT_ERROR_N(store, true)
 #define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size)                      \
   extern "C" NOINLINE INTERFACE_ATTRIBUTE                                      \
   void __asan_##type##size(uptr addr) {                                        \
-    ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0)                  \
+    ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, true)            \
   }                                                                            \
   extern "C" NOINLINE INTERFACE_ATTRIBUTE                                      \
   void __asan_exp_##type##size(uptr addr, u32 exp) {                           \
-    ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp)                \
-  }
+    ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp, true)          \
+  }                                                                            \
+  extern "C" NOINLINE INTERFACE_ATTRIBUTE                                      \
+  void __asan_##type##size ## _noabort(uptr addr) {                            \
+    ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, false)           \
+  }                                                                            \
 
 ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1)
 ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2)
@@ -190,7 +205,7 @@ NOINLINE INTERFACE_ATTRIBUTE
 void __asan_loadN(uptr addr, uptr size) {
   if (__asan_region_is_poisoned(addr, size)) {
     GET_CALLER_PC_BP_SP;
-    __asan_report_error(pc, bp, sp, addr, false, size, 0);
+    ReportGenericError(pc, bp, sp, addr, false, size, 0, true);
   }
 }
 
@@ -199,7 +214,16 @@ NOINLINE INTERFACE_ATTRIBUTE
 void __asan_exp_loadN(uptr addr, uptr size, u32 exp) {
   if (__asan_region_is_poisoned(addr, size)) {
     GET_CALLER_PC_BP_SP;
-    __asan_report_error(pc, bp, sp, addr, false, size, exp);
+    ReportGenericError(pc, bp, sp, addr, false, size, exp, true);
+  }
+}
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_loadN_noabort(uptr addr, uptr size) {
+  if (__asan_region_is_poisoned(addr, size)) {
+    GET_CALLER_PC_BP_SP;
+    ReportGenericError(pc, bp, sp, addr, false, size, 0, false);
   }
 }
 
@@ -208,7 +232,7 @@ NOINLINE INTERFACE_ATTRIBUTE
 void __asan_storeN(uptr addr, uptr size) {
   if (__asan_region_is_poisoned(addr, size)) {
     GET_CALLER_PC_BP_SP;
-    __asan_report_error(pc, bp, sp, addr, true, size, 0);
+    ReportGenericError(pc, bp, sp, addr, true, size, 0, true);
   }
 }
 
@@ -217,7 +241,16 @@ NOINLINE INTERFACE_ATTRIBUTE
 void __asan_exp_storeN(uptr addr, uptr size, u32 exp) {
   if (__asan_region_is_poisoned(addr, size)) {
     GET_CALLER_PC_BP_SP;
-    __asan_report_error(pc, bp, sp, addr, true, size, exp);
+    ReportGenericError(pc, bp, sp, addr, true, size, exp, true);
+  }
+}
+
+extern "C"
+NOINLINE INTERFACE_ATTRIBUTE
+void __asan_storeN_noabort(uptr addr, uptr size) {
+  if (__asan_region_is_poisoned(addr, size)) {
+    GET_CALLER_PC_BP_SP;
+    ReportGenericError(pc, bp, sp, addr, true, size, 0, false);
   }
 }
 

Modified: compiler-rt/trunk/test/asan/TestCases/Darwin/interface_symbols_darwin.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Darwin/interface_symbols_darwin.c?rev=252723&r1=252722&r2=252723&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Darwin/interface_symbols_darwin.c (original)
+++ compiler-rt/trunk/test/asan/TestCases/Darwin/interface_symbols_darwin.c Wed Nov 11 05:59:38 2015
@@ -29,6 +29,18 @@
 // RUN: echo __asan_report_store16 >> %t.interface
 // RUN: echo __asan_report_load_n >> %t.interface
 // RUN: echo __asan_report_store_n >> %t.interface
+// RUN: echo __asan_report_load1_noabort >> %t.interface
+// RUN: echo __asan_report_load2_noabort >> %t.interface
+// RUN: echo __asan_report_load4_noabort >> %t.interface
+// RUN: echo __asan_report_load8_noabort >> %t.interface
+// RUN: echo __asan_report_load16_noabort >> %t.interface
+// RUN: echo __asan_report_store1_noabort >> %t.interface
+// RUN: echo __asan_report_store2_noabort >> %t.interface
+// RUN: echo __asan_report_store4_noabort >> %t.interface
+// RUN: echo __asan_report_store8_noabort >> %t.interface
+// RUN: echo __asan_report_store16_noabort >> %t.interface
+// RUN: echo __asan_report_load_n_noabort >> %t.interface
+// RUN: echo __asan_report_store_n_noabort >> %t.interface
 // RUN: echo __asan_report_exp_load1 >> %t.interface
 // RUN: echo __asan_report_exp_load2 >> %t.interface
 // RUN: echo __asan_report_exp_load4 >> %t.interface

Added: compiler-rt/trunk/test/asan/TestCases/Linux/halt_on_error-torture.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/halt_on_error-torture.cc?rev=252723&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/halt_on_error-torture.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/halt_on_error-torture.cc Wed Nov 11 05:59:38 2015
@@ -0,0 +1,79 @@
+// Stress test recovery mode with many threads.
+//
+// RUN: %clangxx_asan -fsanitize-recover=address %s -o %t
+//
+// RUN: env ASAN_OPTIONS=halt_on_error=false:max_errors=1000 %run %t 1 10 >1.txt 2>&1
+// RUN: FileCheck %s < 1.txt
+// RUN: [ $(wc -l < 1.txt) -gt 1 ]
+//
+// RUN: env ASAN_OPTIONS=halt_on_error=false:max_errors=1000 %run %t 10 20 >10.txt 2>&1
+// RUN: FileCheck %s < 10.txt
+// This one is racy although very unlikely to fail:
+// RUN: [ $(wc -l < 10.txt) -gt 1 ]
+// Collisions are highly unlikely but still possible so we need the alternative:
+// RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 1.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 1.txt
+//
+// REQUIRES: stable-runtime
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <time.h>
+
+#include <sanitizer/asan_interface.h>
+
+size_t nthreads = 10;
+size_t niter = 10;
+
+void *run(void *arg) {
+  unsigned seed = (unsigned)(size_t)arg;
+
+  volatile char tmp[2];
+  __asan_poison_memory_region(&tmp, sizeof(tmp)); 
+
+  for (size_t i = 0; i < niter; ++i) {
+    struct timespec delay = { 0, rand_r(&seed) * 1000000 };
+    nanosleep(&delay, 0);
+
+    // Expect error collisions here
+    // CHECK: AddressSanitizer: use-after-poison
+    volatile int idx = 0;
+    tmp[idx] = 0;
+  }
+
+  return 0;
+}
+
+int main(int argc, char **argv) {
+  if (argc != 3) {
+    fprintf(stderr, "Syntax: %s nthreads niter\n", argv[0]);
+    exit(1);
+  }
+
+  nthreads = (size_t)strtoul(argv[1], 0, 0);
+  niter = (size_t)strtoul(argv[2], 0, 0);
+
+  pthread_t *tids = new pthread_t[nthreads];
+
+  for (size_t i = 0; i < nthreads; ++i) {
+    if (0 != pthread_create(&tids[i], 0, run, (void *)i)) {
+      fprintf(stderr, "Failed to create thread\n");
+      exit(1);
+    }
+  }
+
+  for (size_t i = 0; i < nthreads; ++i) {
+    if (0 != pthread_join(tids[i], 0)) {
+      fprintf(stderr, "Failed to join thread\n");
+      exit(1);
+    }
+  }
+
+  // CHECK-COLLISION: AddressSanitizer: nested bug in the same thread, aborting
+  // CHECK-NO-COLLISION: All threads terminated
+  printf("All threads terminated\n");
+
+  delete [] tids;
+
+  return 0;
+}

Modified: compiler-rt/trunk/test/asan/TestCases/Linux/interface_symbols_linux.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/interface_symbols_linux.c?rev=252723&r1=252722&r2=252723&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/interface_symbols_linux.c (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/interface_symbols_linux.c Wed Nov 11 05:59:38 2015
@@ -24,6 +24,18 @@
 // RUN: echo __asan_report_store16 >> %t.interface
 // RUN: echo __asan_report_load_n >> %t.interface
 // RUN: echo __asan_report_store_n >> %t.interface
+// RUN: echo __asan_report_load1_noabort >> %t.interface
+// RUN: echo __asan_report_load2_noabort >> %t.interface
+// RUN: echo __asan_report_load4_noabort >> %t.interface
+// RUN: echo __asan_report_load8_noabort >> %t.interface
+// RUN: echo __asan_report_load16_noabort >> %t.interface
+// RUN: echo __asan_report_store1_noabort >> %t.interface
+// RUN: echo __asan_report_store2_noabort >> %t.interface
+// RUN: echo __asan_report_store4_noabort >> %t.interface
+// RUN: echo __asan_report_store8_noabort >> %t.interface
+// RUN: echo __asan_report_store16_noabort >> %t.interface
+// RUN: echo __asan_report_load_n_noabort >> %t.interface
+// RUN: echo __asan_report_store_n_noabort >> %t.interface
 // RUN: echo __asan_report_exp_load1 >> %t.interface
 // RUN: echo __asan_report_exp_load2 >> %t.interface
 // RUN: echo __asan_report_exp_load4 >> %t.interface

Added: compiler-rt/trunk/test/asan/TestCases/halt_on_error-1.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/halt_on_error-1.c?rev=252723&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/halt_on_error-1.c (added)
+++ compiler-rt/trunk/test/asan/TestCases/halt_on_error-1.c Wed Nov 11 05:59:38 2015
@@ -0,0 +1,29 @@
+// Test recovery mode.
+//
+// RUN: %clang_asan -fsanitize-recover=address %s -o %t
+//
+// RUN: env not %run %t 2>&1 | FileCheck %s
+// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:halt_on_error=true not %run %t 2>&1 | FileCheck %s
+// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:halt_on_error=false %run %t 2>&1 | FileCheck %s --check-prefix CHECK-RECOVER
+
+#include <string.h>
+
+volatile int ten = 10;
+
+int main() {
+  char x[10];
+  // CHECK: WRITE of size 11
+  // CHECK-RECOVER: WRITE of size 11
+  memset(x, 0, 11);
+  // CHECK-NOT: READ of size 1
+  // CHECK-RECOVER: READ of size 1
+  volatile int res = x[ten];
+  // CHECK-NOT: WRITE of size 1
+  // CHECK-RECOVER: WRITE of size 1
+  x[ten] = res + 3;
+  // CHECK-NOT: READ of size 1
+  // CHECK-RECOVER: READ of size 1
+  res = x[ten];
+  return  0;
+}
+




More information about the llvm-commits mailing list