[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