[compiler-rt] r328722 - [ASan] Report proper ASan error on allocator failures instead of CHECK(0)-ing

Alex Shlyapnikov via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 28 11:22:41 PDT 2018


Author: alekseyshl
Date: Wed Mar 28 11:22:40 2018
New Revision: 328722

URL: http://llvm.org/viewvc/llvm-project?rev=328722&view=rev
Log:
[ASan] Report proper ASan error on allocator failures instead of CHECK(0)-ing

Summary:
Currently many allocator specific errors (OOM, for example) are reported as
a text message and CHECK(0) termination, not stack, no details, not too
helpful nor informative. To improve the situation, ASan detailed errors were
defined and reported under the appropriate conditions.

Issue: https://github.com/google/sanitizers/issues/887

Reviewers: eugenis

Subscribers: kubamracek, delcypher, #sanitizers, llvm-commits

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

Added:
    compiler-rt/trunk/test/asan/TestCases/Linux/aligned_alloc-alignment.cc
    compiler-rt/trunk/test/asan/TestCases/Posix/posix_memalign-alignment.cc
    compiler-rt/trunk/test/asan/TestCases/calloc-overflow.cc
    compiler-rt/trunk/test/asan/TestCases/malloc-size-too-big.cc
Modified:
    compiler-rt/trunk/lib/asan/asan_allocator.cc
    compiler-rt/trunk/lib/asan/asan_errors.cc
    compiler-rt/trunk/lib/asan/asan_errors.h
    compiler-rt/trunk/lib/asan/asan_new_delete.cc
    compiler-rt/trunk/lib/asan/asan_report.cc
    compiler-rt/trunk/lib/asan/asan_report.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h
    compiler-rt/trunk/test/asan/TestCases/Linux/allocator_oom_test.cc
    compiler-rt/trunk/test/asan/TestCases/Linux/pvalloc-overflow.cc
    compiler-rt/trunk/test/asan/TestCases/Windows/oom.cc
    compiler-rt/trunk/test/asan/TestCases/allocator_returns_null.cc
    compiler-rt/trunk/test/lsan/TestCases/allocator_returns_null.cc
    compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc

Modified: compiler-rt/trunk/lib/asan/asan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator.cc?rev=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator.cc Wed Mar 28 11:22:40 2018
@@ -134,8 +134,9 @@ struct AsanChunk: ChunkBase {
 };
 
 struct QuarantineCallback {
-  explicit QuarantineCallback(AllocatorCache *cache)
-      : cache_(cache) {
+  QuarantineCallback(AllocatorCache *cache, BufferedStackTrace *stack)
+      : cache_(cache),
+        stack_(stack) {
   }
 
   void Recycle(AsanChunk *m) {
@@ -168,7 +169,7 @@ struct QuarantineCallback {
     void *res = get_allocator().Allocate(cache_, size, 1);
     // TODO(alekseys): Consider making quarantine OOM-friendly.
     if (UNLIKELY(!res))
-      return DieOnFailure::OnOOM();
+      ReportOutOfMemory(size, stack_);
     return res;
   }
 
@@ -176,7 +177,9 @@ struct QuarantineCallback {
     get_allocator().Deallocate(cache_, p);
   }
 
-  AllocatorCache *cache_;
+ private:
+  AllocatorCache* const cache_;
+  BufferedStackTrace* const stack_;
 };
 
 typedef Quarantine<QuarantineCallback, AsanChunk> AsanQuarantine;
@@ -397,8 +400,11 @@ struct Allocator {
                  AllocType alloc_type, bool can_fill) {
     if (UNLIKELY(!asan_inited))
       AsanInitFromRtl();
-    if (RssLimitExceeded())
-      return ReturnNullOrDieOnFailure::OnOOM();
+    if (RssLimitExceeded()) {
+      if (AllocatorMayReturnNull())
+        return nullptr;
+      ReportRssLimitExceeded(stack);
+    }
     Flags &fl = *flags();
     CHECK(stack);
     const uptr min_alignment = SHADOW_GRANULARITY;
@@ -431,9 +437,13 @@ struct Allocator {
     }
     CHECK(IsAligned(needed_size, min_alignment));
     if (size > kMaxAllowedMallocSize || needed_size > kMaxAllowedMallocSize) {
-      Report("WARNING: AddressSanitizer failed to allocate 0x%zx bytes\n",
-             (void*)size);
-      return ReturnNullOrDieOnFailure::OnBadRequest();
+      if (AllocatorMayReturnNull()) {
+        Report("WARNING: AddressSanitizer failed to allocate 0x%zx bytes\n",
+               (void*)size);
+        return nullptr;
+      }
+      ReportAllocationSizeTooBig(size, needed_size, kMaxAllowedMallocSize,
+                                 stack);
     }
 
     AsanThread *t = GetCurrentThread();
@@ -446,8 +456,12 @@ struct Allocator {
       AllocatorCache *cache = &fallback_allocator_cache;
       allocated = allocator.Allocate(cache, needed_size, 8);
     }
-    if (UNLIKELY(!allocated))
-      return ReturnNullOrDieOnFailure::OnOOM();
+    if (UNLIKELY(!allocated)) {
+      SetAllocatorOutOfMemory();
+      if (AllocatorMayReturnNull())
+        return nullptr;
+      ReportOutOfMemory(size, stack);
+    }
 
     if (*(u8 *)MEM_TO_SHADOW((uptr)allocated) == 0 && CanPoisonMemory()) {
       // Heap poisoning is enabled, but the allocator provides an unpoisoned
@@ -583,13 +597,13 @@ struct Allocator {
     if (t) {
       AsanThreadLocalMallocStorage *ms = &t->malloc_storage();
       AllocatorCache *ac = GetAllocatorCache(ms);
-      quarantine.Put(GetQuarantineCache(ms), QuarantineCallback(ac), m,
-                           m->UsedSize());
+      quarantine.Put(GetQuarantineCache(ms), QuarantineCallback(ac, stack), m,
+                     m->UsedSize());
     } else {
       SpinMutexLock l(&fallback_mutex);
       AllocatorCache *ac = &fallback_allocator_cache;
-      quarantine.Put(&fallback_quarantine_cache, QuarantineCallback(ac), m,
-                           m->UsedSize());
+      quarantine.Put(&fallback_quarantine_cache, QuarantineCallback(ac, stack),
+                     m, m->UsedSize());
     }
   }
 
@@ -660,8 +674,11 @@ struct Allocator {
   }
 
   void *Calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) {
-    if (UNLIKELY(CheckForCallocOverflow(size, nmemb)))
-      return ReturnNullOrDieOnFailure::OnBadRequest();
+    if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+      if (AllocatorMayReturnNull())
+        return nullptr;
+      ReportCallocOverflow(nmemb, size, stack);
+    }
     void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC, false);
     // If the memory comes from the secondary allocator no need to clear it
     // as it comes directly from mmap.
@@ -677,9 +694,9 @@ struct Allocator {
       ReportFreeNotMalloced((uptr)ptr, stack);
   }
 
-  void CommitBack(AsanThreadLocalMallocStorage *ms) {
+  void CommitBack(AsanThreadLocalMallocStorage *ms, BufferedStackTrace *stack) {
     AllocatorCache *ac = GetAllocatorCache(ms);
-    quarantine.Drain(GetQuarantineCache(ms), QuarantineCallback(ac));
+    quarantine.Drain(GetQuarantineCache(ms), QuarantineCallback(ac, stack));
     allocator.SwallowCache(ac);
   }
 
@@ -739,17 +756,19 @@ struct Allocator {
     return AsanChunkView(m1);
   }
 
-  void Purge() {
+  void Purge(BufferedStackTrace *stack) {
     AsanThread *t = GetCurrentThread();
     if (t) {
       AsanThreadLocalMallocStorage *ms = &t->malloc_storage();
       quarantine.DrainAndRecycle(GetQuarantineCache(ms),
-                                 QuarantineCallback(GetAllocatorCache(ms)));
+                                 QuarantineCallback(GetAllocatorCache(ms),
+                                                    stack));
     }
     {
       SpinMutexLock l(&fallback_mutex);
       quarantine.DrainAndRecycle(&fallback_quarantine_cache,
-                                 QuarantineCallback(&fallback_allocator_cache));
+                                 QuarantineCallback(&fallback_allocator_cache,
+                                                    stack));
     }
 
     allocator.ForceReleaseToOS();
@@ -836,7 +855,8 @@ AsanChunkView FindHeapChunkByAllocBeg(up
 }
 
 void AsanThreadLocalMallocStorage::CommitBack() {
-  instance.CommitBack(this);
+  GET_STACK_TRACE_MALLOC;
+  instance.CommitBack(this, &stack);
 }
 
 void PrintInternalAllocatorStats() {
@@ -883,7 +903,9 @@ void *asan_pvalloc(uptr size, BufferedSt
   uptr PageSize = GetPageSizeCached();
   if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) {
     errno = errno_ENOMEM;
-    return ReturnNullOrDieOnFailure::OnBadRequest();
+    if (AllocatorMayReturnNull())
+      return nullptr;
+    ReportPvallocOverflow(size, stack);
   }
   // pvalloc(0) should allocate one page.
   size = size ? RoundUpTo(size, PageSize) : PageSize;
@@ -895,7 +917,9 @@ void *asan_memalign(uptr alignment, uptr
                     AllocType alloc_type) {
   if (UNLIKELY(!IsPowerOfTwo(alignment))) {
     errno = errno_EINVAL;
-    return ReturnNullOrDieOnFailure::OnBadRequest();
+    if (AllocatorMayReturnNull())
+      return nullptr;
+    ReportInvalidAllocationAlignment(alignment, stack);
   }
   return SetErrnoOnNull(
       instance.Allocate(size, alignment, stack, alloc_type, true));
@@ -904,11 +928,13 @@ void *asan_memalign(uptr alignment, uptr
 int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
                         BufferedStackTrace *stack) {
   if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
-    ReturnNullOrDieOnFailure::OnBadRequest();
-    return errno_EINVAL;
+    if (AllocatorMayReturnNull())
+      return errno_EINVAL;
+    ReportInvalidPosixMemalignAlignment(alignment, stack);
   }
   void *ptr = instance.Allocate(size, alignment, stack, FROM_MALLOC, true);
   if (UNLIKELY(!ptr))
+    // OOM error is already taken care of by Allocate.
     return errno_ENOMEM;
   CHECK(IsAligned((uptr)ptr, alignment));
   *memptr = ptr;
@@ -1054,7 +1080,8 @@ uptr __sanitizer_get_allocated_size(cons
 }
 
 void __sanitizer_purge_allocator() {
-  instance.Purge();
+  GET_STACK_TRACE_MALLOC;
+  instance.Purge(&stack);
 }
 
 #if !SANITIZER_SUPPORTS_WEAK_HOOKS

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=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_errors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_errors.cc Wed Mar 28 11:22:40 2018
@@ -172,6 +172,106 @@ void ErrorSanitizerGetAllocatedSizeNotOw
   ReportErrorSummary(scariness.GetDescription(), stack);
 }
 
+void ErrorCallocOverflow::Print() {
+  Decorator d;
+  Printf("%s", d.Warning());
+  char tname[128];
+  Report(
+      "ERROR: AddressSanitizer: calloc parameters overflow: count * size "
+      "(%zd * %zd) cannot be represented in type size_t (thread T%d%s)\n",
+      count, size, tid, ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
+  Printf("%s", d.Default());
+  stack->Print();
+  PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+  ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorPvallocOverflow::Print() {
+  Decorator d;
+  Printf("%s", d.Warning());
+  char tname[128];
+  Report(
+      "ERROR: AddressSanitizer: pvalloc parameters overflow: size 0x%zx "
+      "rounded up to system page size 0x%zx cannot be represented in type "
+      "size_t (thread T%d%s)\n",
+      size, GetPageSizeCached(), tid,
+      ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
+  Printf("%s", d.Default());
+  stack->Print();
+  PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+  ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorInvalidAllocationAlignment::Print() {
+  Decorator d;
+  Printf("%s", d.Warning());
+  char tname[128];
+  Report(
+      "ERROR: AddressSanitizer: invalid allocation alignment: %zd, "
+      "alignment must be a power of two (thread T%d%s)\n",
+      alignment, tid, ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
+  Printf("%s", d.Default());
+  stack->Print();
+  PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+  ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorInvalidPosixMemalignAlignment::Print() {
+  Decorator d;
+  Printf("%s", d.Warning());
+  char tname[128];
+  Report(
+      "ERROR: AddressSanitizer: invalid alignment requested in posix_memalign: "
+      "%zd, alignment must be a power of two and a multiple of sizeof(void*) "
+      "== %zd (thread T%d%s)\n",
+      alignment, sizeof(void*), tid,  // NOLINT
+      ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
+  Printf("%s", d.Default());
+  stack->Print();
+  PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+  ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorAllocationSizeTooBig::Print() {
+  Decorator d;
+  Printf("%s", d.Warning());
+  char tname[128];
+  Report(
+      "ERROR: AddressSanitizer: requested allocation size 0x%zx (0x%zx after "
+      "adjustments for alignment, red zones etc.) exceeds maximum supported "
+      "size of 0x%zx (thread T%d%s)\n",
+      user_size, total_size, max_size, tid,
+      ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
+  Printf("%s", d.Default());
+  stack->Print();
+  PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+  ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorRssLimitExceeded::Print() {
+  Decorator d;
+  Printf("%s", d.Warning());
+  Report(
+      "ERROR: AddressSanitizer: specified RSS limit exceeded, currently set to "
+      "soft_rss_limit_mb=%zd\n", common_flags()->soft_rss_limit_mb);
+  Printf("%s", d.Default());
+  stack->Print();
+  PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+  ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
+void ErrorOutOfMemory::Print() {
+  Decorator d;
+  Printf("%s", d.Warning());
+  Report(
+      "ERROR: AddressSanitizer: allocator is out of memory trying to allocate "
+      "0x%zx bytes\n", requested_size);
+  Printf("%s", d.Default());
+  stack->Print();
+  PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+  ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
 void ErrorStringFunctionMemoryRangesOverlap::Print() {
   Decorator d;
   char bug_type[100];

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=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_errors.h (original)
+++ compiler-rt/trunk/lib/asan/asan_errors.h Wed Mar 28 11:22:40 2018
@@ -23,6 +23,10 @@ namespace __asan {
 struct ErrorBase {
   ErrorBase() = default;
   explicit ErrorBase(u32 tid_) : tid(tid_) {}
+  ErrorBase(u32 tid_, int initial_score, const char *reason) : tid(tid_) {
+    scariness.Clear();
+    scariness.Scare(initial_score, reason);
+  }
   ScarinessScoreBase scariness;
   u32 tid;
 };
@@ -164,6 +168,105 @@ struct ErrorSanitizerGetAllocatedSizeNot
   void Print();
 };
 
+struct ErrorCallocOverflow : ErrorBase {
+  const BufferedStackTrace *stack;
+  uptr count;
+  uptr size;
+  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
+  // constructor
+  ErrorCallocOverflow() = default;
+  ErrorCallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
+                      uptr size_)
+      : ErrorBase(tid, 10, "calloc-overflow"),
+        stack(stack_),
+        count(count_),
+        size(size_) {}
+  void Print();
+};
+
+struct ErrorPvallocOverflow : ErrorBase {
+  const BufferedStackTrace *stack;
+  uptr size;
+  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
+  // constructor
+  ErrorPvallocOverflow() = default;
+  ErrorPvallocOverflow(u32 tid, BufferedStackTrace *stack_, uptr size_)
+      : ErrorBase(tid, 10, "pvalloc-overflow"),
+        stack(stack_),
+        size(size_) {}
+  void Print();
+};
+
+struct ErrorInvalidAllocationAlignment : ErrorBase {
+  const BufferedStackTrace *stack;
+  uptr alignment;
+  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
+  // constructor
+  ErrorInvalidAllocationAlignment() = default;
+  ErrorInvalidAllocationAlignment(u32 tid, BufferedStackTrace *stack_,
+                                  uptr alignment_)
+      : ErrorBase(tid, 10, "invalid-allocation-alignment"),
+        stack(stack_),
+        alignment(alignment_) {}
+  void Print();
+};
+
+struct ErrorInvalidPosixMemalignAlignment : ErrorBase {
+  const BufferedStackTrace *stack;
+  uptr alignment;
+  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
+  // constructor
+  ErrorInvalidPosixMemalignAlignment() = default;
+  ErrorInvalidPosixMemalignAlignment(u32 tid, BufferedStackTrace *stack_,
+                                     uptr alignment_)
+      : ErrorBase(tid, 10, "invalid-posix-memalign-alignment"),
+        stack(stack_),
+        alignment(alignment_) {}
+  void Print();
+};
+
+struct ErrorAllocationSizeTooBig : ErrorBase {
+  const BufferedStackTrace *stack;
+  uptr user_size;
+  uptr total_size;
+  uptr max_size;
+  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
+  // constructor
+  ErrorAllocationSizeTooBig() = default;
+  ErrorAllocationSizeTooBig(u32 tid, BufferedStackTrace *stack_,
+                            uptr user_size_, uptr total_size_, uptr max_size_)
+      : ErrorBase(tid, 10, "allocation-size-too-big"),
+        stack(stack_),
+        user_size(user_size_),
+        total_size(total_size_),
+        max_size(max_size_) {}
+  void Print();
+};
+
+struct ErrorRssLimitExceeded : ErrorBase {
+  const BufferedStackTrace *stack;
+  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
+  // constructor
+  ErrorRssLimitExceeded() = default;
+  ErrorRssLimitExceeded(u32 tid, BufferedStackTrace *stack_)
+      : ErrorBase(tid, 10, "rss-limit-exceeded"),
+        stack(stack_) {}
+  void Print();
+};
+
+struct ErrorOutOfMemory : ErrorBase {
+  const BufferedStackTrace *stack;
+  uptr requested_size;
+  // VS2013 doesn't implement unrestricted unions, so we need a trivial default
+  // constructor
+  ErrorOutOfMemory() = default;
+  ErrorOutOfMemory(u32 tid, BufferedStackTrace *stack_, uptr requested_size_)
+      : ErrorBase(tid, 10, "out-of-memory"),
+        stack(stack_),
+        requested_size(requested_size_) {}
+  void Print();
+};
+
 struct ErrorStringFunctionMemoryRangesOverlap : ErrorBase {
   // ErrorStringFunctionMemoryRangesOverlap doesn't own the stack trace.
   const BufferedStackTrace *stack;
@@ -300,6 +403,13 @@ struct ErrorGeneric : ErrorBase {
   macro(AllocTypeMismatch)                      \
   macro(MallocUsableSizeNotOwned)               \
   macro(SanitizerGetAllocatedSizeNotOwned)      \
+  macro(CallocOverflow)                         \
+  macro(PvallocOverflow)                        \
+  macro(InvalidAllocationAlignment)             \
+  macro(InvalidPosixMemalignAlignment)          \
+  macro(AllocationSizeTooBig)                   \
+  macro(RssLimitExceeded)                       \
+  macro(OutOfMemory)                            \
   macro(StringFunctionMemoryRangesOverlap)      \
   macro(StringFunctionSizeOverflow)             \
   macro(BadParamsToAnnotateContiguousContainer) \

Modified: compiler-rt/trunk/lib/asan/asan_new_delete.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_new_delete.cc?rev=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_new_delete.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_new_delete.cc Wed Mar 28 11:22:40 2018
@@ -14,6 +14,7 @@
 
 #include "asan_allocator.h"
 #include "asan_internal.h"
+#include "asan_report.h"
 #include "asan_stack.h"
 
 #include "interception/interception.h"
@@ -67,16 +68,16 @@ struct nothrow_t {};
 enum class align_val_t: size_t {};
 }  // namespace std
 
-// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
+// TODO(alekseyshl): throw std::bad_alloc instead of dying on OOM.
 #define OPERATOR_NEW_BODY(type, nothrow) \
   GET_STACK_TRACE_MALLOC;\
   void *res = asan_memalign(0, size, &stack, type);\
-  if (!nothrow && UNLIKELY(!res)) DieOnFailure::OnOOM();\
+  if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
   return res;
 #define OPERATOR_NEW_BODY_ALIGN(type, nothrow) \
   GET_STACK_TRACE_MALLOC;\
   void *res = asan_memalign((uptr)align, size, &stack, type);\
-  if (!nothrow && UNLIKELY(!res)) DieOnFailure::OnOOM();\
+  if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
   return res;
 
 // On OS X it's not enough to just provide our own 'operator new' and

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=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Wed Mar 28 11:22:40 2018
@@ -254,6 +254,54 @@ void ReportSanitizerGetAllocatedSizeNotO
   in_report.ReportError(error);
 }
 
+void ReportCallocOverflow(uptr count, uptr size, BufferedStackTrace *stack) {
+  ScopedInErrorReport in_report(/*fatal*/ true);
+  ErrorCallocOverflow error(GetCurrentTidOrInvalid(), stack, count, size);
+  in_report.ReportError(error);
+}
+
+void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack) {
+  ScopedInErrorReport in_report(/*fatal*/ true);
+  ErrorPvallocOverflow error(GetCurrentTidOrInvalid(), stack, size);
+  in_report.ReportError(error);
+}
+
+void ReportInvalidAllocationAlignment(uptr alignment,
+                                      BufferedStackTrace *stack) {
+  ScopedInErrorReport in_report(/*fatal*/ true);
+  ErrorInvalidAllocationAlignment error(GetCurrentTidOrInvalid(), stack,
+                                        alignment);
+  in_report.ReportError(error);
+}
+
+void ReportInvalidPosixMemalignAlignment(uptr alignment,
+                                         BufferedStackTrace *stack) {
+  ScopedInErrorReport in_report(/*fatal*/ true);
+  ErrorInvalidPosixMemalignAlignment error(GetCurrentTidOrInvalid(), stack,
+                                           alignment);
+  in_report.ReportError(error);
+}
+
+void ReportAllocationSizeTooBig(uptr user_size, uptr total_size, uptr max_size,
+                                BufferedStackTrace *stack) {
+  ScopedInErrorReport in_report(/*fatal*/ true);
+  ErrorAllocationSizeTooBig error(GetCurrentTidOrInvalid(), stack, user_size,
+                                  total_size, max_size);
+  in_report.ReportError(error);
+}
+
+void ReportRssLimitExceeded(BufferedStackTrace *stack) {
+  ScopedInErrorReport in_report(/*fatal*/ true);
+  ErrorRssLimitExceeded error(GetCurrentTidOrInvalid(), stack);
+  in_report.ReportError(error);
+}
+
+void ReportOutOfMemory(uptr requested_size, BufferedStackTrace *stack) {
+  ScopedInErrorReport in_report(/*fatal*/ true);
+  ErrorOutOfMemory error(GetCurrentTidOrInvalid(), stack, requested_size);
+  in_report.ReportError(error);
+}
+
 void ReportStringFunctionMemoryRangesOverlap(const char *function,
                                              const char *offset1, uptr length1,
                                              const char *offset2, uptr length2,

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=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.h (original)
+++ compiler-rt/trunk/lib/asan/asan_report.h Wed Mar 28 11:22:40 2018
@@ -58,6 +58,16 @@ void ReportAllocTypeMismatch(uptr addr,
 void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack);
 void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
                                              BufferedStackTrace *stack);
+void ReportCallocOverflow(uptr count, uptr size, BufferedStackTrace *stack);
+void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack);
+void ReportInvalidAllocationAlignment(uptr alignment,
+                                      BufferedStackTrace *stack);
+void ReportInvalidPosixMemalignAlignment(uptr alignment,
+                                         BufferedStackTrace *stack);
+void ReportAllocationSizeTooBig(uptr user_size, uptr total_size, uptr max_size,
+                                BufferedStackTrace *stack);
+void ReportRssLimitExceeded(BufferedStackTrace *stack);
+void ReportOutOfMemory(uptr requested_size, BufferedStackTrace *stack);
 void ReportStringFunctionMemoryRangesOverlap(const char *function,
                                              const char *offset1, uptr length1,
                                              const char *offset2, uptr length2,

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.cc?rev=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.cc Wed Mar 28 11:22:40 2018
@@ -218,6 +218,10 @@ bool IsAllocatorOutOfMemory() {
   return atomic_load_relaxed(&allocator_out_of_memory);
 }
 
+void SetAllocatorOutOfMemory() {
+  atomic_store_relaxed(&allocator_out_of_memory, 1);
+}
+
 // Prints error message and kills the program.
 void NORETURN ReportAllocatorCannotReturnNull() {
   Report("%s's allocator is terminating the process instead of returning 0\n",
@@ -258,4 +262,10 @@ void NORETURN *DieOnFailure::OnOOM() {
   ReportAllocatorCannotReturnNull();
 }
 
+// Prints hint message.
+void PrintHintAllocatorCannotReturnNull(const char *options_name) {
+  Report("HINT: if you don't care about these errors you may set "
+         "%s=allocator_may_return_null=1\n", options_name);
+}
+
 } // namespace __sanitizer

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h?rev=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.h Wed Mar 28 11:22:40 2018
@@ -43,9 +43,12 @@ struct DieOnFailure {
   static void NORETURN *OnOOM();
 };
 
+void PrintHintAllocatorCannotReturnNull(const char *options_name);
+
 // Returns true if allocator detected OOM condition. Can be used to avoid memory
 // hungry operations. Set when AllocatorReturnNullOrDieOnOOM() is called.
 bool IsAllocatorOutOfMemory();
+void SetAllocatorOutOfMemory();
 
 // Allocators call these callbacks on mmap/munmap.
 struct NoOpMapUnmapCallback {

Added: compiler-rt/trunk/test/asan/TestCases/Linux/aligned_alloc-alignment.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/aligned_alloc-alignment.cc?rev=328722&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/aligned_alloc-alignment.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/aligned_alloc-alignment.cc Wed Mar 28 11:22:40 2018
@@ -0,0 +1,19 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+  void *p = aligned_alloc(17, 100);
+  // CHECK: ERROR: AddressSanitizer: invalid allocation alignment: 17
+  // CHECK: {{#0 0x.* in .*aligned_alloc}}
+  // CHECK: {{#1 0x.* in main .*aligned_alloc-alignment.cc:}}[[@LINE-3]]
+  // CHECK: SUMMARY: AddressSanitizer: invalid-allocation-alignment
+
+  printf("pointer after failed aligned_alloc: %zd\n", (size_t)p);
+  // CHECK-NULL: pointer after failed aligned_alloc: 0
+
+  return 0;
+}

Modified: compiler-rt/trunk/test/asan/TestCases/Linux/allocator_oom_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/allocator_oom_test.cc?rev=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/allocator_oom_test.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/allocator_oom_test.cc Wed Mar 28 11:22:40 2018
@@ -84,5 +84,5 @@ int main(int argc, char **argv) {
 // CHECK-REALLOC: realloc:
 // CHECK-MALLOC-REALLOC: realloc-after-malloc:
 
-// CHECK-CRASH: AddressSanitizer's allocator is terminating the process
+// CHECK-CRASH: SUMMARY: AddressSanitizer: out-of-memory
 // CHECK-NULL: x: 0

Modified: compiler-rt/trunk/test/asan/TestCases/Linux/pvalloc-overflow.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/pvalloc-overflow.cc?rev=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/pvalloc-overflow.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/pvalloc-overflow.cc Wed Mar 28 11:22:40 2018
@@ -38,4 +38,7 @@ int main(int argc, char *argv[]) {
   return 0;
 }
 
-// CHECK: AddressSanitizer's allocator is terminating the process
+// CHECK: {{ERROR: AddressSanitizer: pvalloc parameters overflow: size .* rounded up to system page size .* cannot be represented in type size_t}}
+// CHECK: {{#0 0x.* in .*pvalloc}}
+// CHECK: {{#1 0x.* in main .*pvalloc-overflow.cc:}}
+// CHECK: SUMMARY: AddressSanitizer: pvalloc-overflow

Added: compiler-rt/trunk/test/asan/TestCases/Posix/posix_memalign-alignment.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Posix/posix_memalign-alignment.cc?rev=328722&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Posix/posix_memalign-alignment.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Posix/posix_memalign-alignment.cc Wed Mar 28 11:22:40 2018
@@ -0,0 +1,20 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+  void *p = reinterpret_cast<void*>(42);
+  int res = posix_memalign(&p, 17, 100);
+  // CHECK: ERROR: AddressSanitizer: invalid alignment requested in posix_memalign: 17
+  // CHECK: {{#0 0x.* in .*posix_memalign}}
+  // CHECK: {{#1 0x.* in main .*posix_memalign-alignment.cc:}}[[@LINE-3]]
+  // CHECK: SUMMARY: AddressSanitizer: invalid-posix-memalign-alignment
+
+  printf("pointer after failed posix_memalign: %zd\n", (size_t)p);
+  // CHECK-NULL: pointer after failed posix_memalign: 42
+
+  return 0;
+}

Modified: compiler-rt/trunk/test/asan/TestCases/Windows/oom.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Windows/oom.cc?rev=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Windows/oom.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Windows/oom.cc Wed Mar 28 11:22:40 2018
@@ -8,5 +8,5 @@ int main() {
   while (true) {
     void *ptr = malloc(200 * 1024 * 1024);  // 200MB
   }
-// CHECK: allocator is terminating the process instead of returning 0
+// CHECK: SUMMARY: AddressSanitizer: out-of-memory
 }

Modified: compiler-rt/trunk/test/asan/TestCases/allocator_returns_null.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/allocator_returns_null.cc?rev=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/allocator_returns_null.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/allocator_returns_null.cc Wed Mar 28 11:22:40 2018
@@ -30,7 +30,7 @@
 // RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t new 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=CHECK-nCRASH
 // RUN: %env_asan_opts=allocator_may_return_null=1 not %run %t new 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-nCRASH
+// RUN:   | FileCheck %s --check-prefix=CHECK-nCRASH-OOM
 // RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=CHECK-nnCRASH
 // RUN: %env_asan_opts=allocator_may_return_null=1     %run %t new-nothrow 2>&1 \
@@ -98,19 +98,21 @@ int main(int argc, char **argv) {
 }
 
 // CHECK-mCRASH: malloc:
-// CHECK-mCRASH: AddressSanitizer's allocator is terminating the process
+// CHECK-mCRASH: SUMMARY: AddressSanitizer: allocation-size-too-big
 // CHECK-cCRASH: calloc:
-// CHECK-cCRASH: AddressSanitizer's allocator is terminating the process
+// CHECK-cCRASH: SUMMARY: AddressSanitizer: allocation-size-too-big
 // CHECK-coCRASH: calloc-overflow:
-// CHECK-coCRASH: AddressSanitizer's allocator is terminating the process
+// CHECK-coCRASH: SUMMARY: AddressSanitizer: calloc-overflow
 // CHECK-rCRASH: realloc:
-// CHECK-rCRASH: AddressSanitizer's allocator is terminating the process
+// CHECK-rCRASH: SUMMARY: AddressSanitizer: allocation-size-too-big
 // CHECK-mrCRASH: realloc-after-malloc:
-// CHECK-mrCRASH: AddressSanitizer's allocator is terminating the process
+// CHECK-mrCRASH: SUMMARY: AddressSanitizer: allocation-size-too-big
 // CHECK-nCRASH: new:
-// CHECK-nCRASH: AddressSanitizer's allocator is terminating the process
+// CHECK-nCRASH: SUMMARY: AddressSanitizer: allocation-size-too-big
+// CHECK-nCRASH-OOM: new:
+// CHECK-nCRASH-OOM: SUMMARY: AddressSanitizer: out-of-memory
 // CHECK-nnCRASH: new-nothrow:
-// CHECK-nnCRASH: AddressSanitizer's allocator is terminating the process
+// CHECK-nnCRASH: SUMMARY: AddressSanitizer: allocation-size-too-big
 
 // CHECK-mNULL: malloc:
 // CHECK-mNULL: errno: 12

Added: compiler-rt/trunk/test/asan/TestCases/calloc-overflow.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/calloc-overflow.cc?rev=328722&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/calloc-overflow.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/calloc-overflow.cc Wed Mar 28 11:22:40 2018
@@ -0,0 +1,19 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main() {
+  void *p = calloc(-1, 1000);
+  // CHECK: {{ERROR: AddressSanitizer: calloc parameters overflow: count \* size \(.* \* 1000\) cannot be represented in type size_t}}
+  // CHECK: {{#0 0x.* in .*calloc}}
+  // CHECK: {{#1 0x.* in main .*calloc-overflow.cc:}}[[@LINE-3]]
+  // CHECK: SUMMARY: AddressSanitizer: calloc-overflow
+
+  printf("calloc returned: %zu\n", (size_t)p);
+  // CHECK-NULL: calloc returned: 0
+
+  return 0;
+}

Added: compiler-rt/trunk/test/asan/TestCases/malloc-size-too-big.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/malloc-size-too-big.cc?rev=328722&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/malloc-size-too-big.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/malloc-size-too-big.cc Wed Mar 28 11:22:40 2018
@@ -0,0 +1,26 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
+// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static const size_t kMaxAllowedMallocSizePlusOne =
+#if __LP64__ || defined(_WIN64)
+    (1ULL << 40) + 1;
+#else
+    (3UL << 30) + 1;
+#endif
+
+int main() {
+  void *p = malloc(kMaxAllowedMallocSizePlusOne);
+  // CHECK: {{ERROR: AddressSanitizer: requested allocation size .* \(.* after adjustments for alignment, red zones etc\.\) exceeds maximum supported size}}
+  // CHECK: {{#0 0x.* in .*malloc}}
+  // CHECK: {{#1 0x.* in main .*malloc-size-too-big.cc:}}[[@LINE-3]]
+  // CHECK: SUMMARY: AddressSanitizer: allocation-size-too-big
+
+  printf("malloc returned: %zu\n", (size_t)p);
+  // CHECK-NULL: malloc returned: 0
+
+  return 0;
+}

Modified: compiler-rt/trunk/test/lsan/TestCases/allocator_returns_null.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/lsan/TestCases/allocator_returns_null.cc?rev=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/test/lsan/TestCases/allocator_returns_null.cc (original)
+++ compiler-rt/trunk/test/lsan/TestCases/allocator_returns_null.cc Wed Mar 28 11:22:40 2018
@@ -30,12 +30,16 @@
 // RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t new 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=CHECK-nCRASH
 // RUN: %env_lsan_opts=allocator_may_return_null=1 not %run %t new 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-nCRASH
+// RUN:   | FileCheck %s --check-prefix=CHECK-nCRASH-OOM
 // RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=CHECK-nnCRASH
 // RUN: %env_lsan_opts=allocator_may_return_null=1     %run %t new-nothrow 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=CHECK-nnNULL
 
+// TODO(alekseyshl): Enable it back for standalone LSan mode when CHECK(0) in
+// LSan allocator are converted to proper errors (see D44404 for the reference).
+// REQUIRES: asan
+
 #include <assert.h>
 #include <errno.h>
 #include <stdio.h>
@@ -98,19 +102,21 @@ int main(int argc, char **argv) {
 }
 
 // CHECK-mCRASH: malloc:
-// CHECK-mCRASH: Sanitizer's allocator is terminating the process
+// CHECK-mCRASH: SUMMARY: AddressSanitizer: allocation-size-too-big
 // CHECK-cCRASH: calloc:
-// CHECK-cCRASH: Sanitizer's allocator is terminating the process
+// CHECK-cCRASH: SUMMARY: AddressSanitizer: allocation-size-too-big
 // CHECK-coCRASH: calloc-overflow:
-// CHECK-coCRASH: Sanitizer's allocator is terminating the process
+// CHECK-coCRASH: SUMMARY: AddressSanitizer: calloc-overflow
 // CHECK-rCRASH: realloc:
-// CHECK-rCRASH: Sanitizer's allocator is terminating the process
+// CHECK-rCRASH: SUMMARY: AddressSanitizer: allocation-size-too-big
 // CHECK-mrCRASH: realloc-after-malloc:
-// CHECK-mrCRASH: Sanitizer's allocator is terminating the process
+// CHECK-mrCRASH: SUMMARY: AddressSanitizer: allocation-size-too-big
 // CHECK-nCRASH: new:
-// CHECK-nCRASH: Sanitizer's allocator is terminating the process
+// CHECK-nCRASH: SUMMARY: AddressSanitizer: allocation-size-too-big
+// CHECK-nCRASH-OOM: new:
+// CHECK-nCRASH-OOM: SUMMARY: AddressSanitizer: out-of-memory
 // CHECK-nnCRASH: new-nothrow:
-// CHECK-nnCRASH: Sanitizer's allocator is terminating the process
+// CHECK-nnCRASH: SUMMARY: AddressSanitizer: allocation-size-too-big
 
 // CHECK-mNULL: malloc:
 // CHECK-mNULL: errno: 12

Modified: compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc?rev=328722&r1=328721&r2=328722&view=diff
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc (original)
+++ compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc Wed Mar 28 11:22:40 2018
@@ -65,4 +65,4 @@ int main() {
 // CHECK_MAY_RETURN_0: allocating 128 times
 // CHECK_MAY_RETURN_0: Some of the malloc calls returned non-null: 128
 // CHECK_MAY_RETURN_0: allocating 256 times
-// CHECK_MAY_RETURN_0: allocator is terminating the process instead of returning
+// CHECK_MAY_RETURN_0: {{SUMMARY: .*Sanitizer: rss-limit-exceeded}}




More information about the llvm-commits mailing list