summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/asan/asan_allocator.cc83
-rw-r--r--compiler-rt/lib/asan/asan_errors.cc100
-rw-r--r--compiler-rt/lib/asan/asan_errors.h110
-rw-r--r--compiler-rt/lib/asan/asan_new_delete.cc7
-rw-r--r--compiler-rt/lib/asan/asan_report.cc48
-rw-r--r--compiler-rt/lib/asan/asan_report.h10
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc10
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_allocator.h3
-rw-r--r--compiler-rt/test/asan/TestCases/Linux/aligned_alloc-alignment.cc19
-rw-r--r--compiler-rt/test/asan/TestCases/Linux/allocator_oom_test.cc2
-rw-r--r--compiler-rt/test/asan/TestCases/Linux/pvalloc-overflow.cc5
-rw-r--r--compiler-rt/test/asan/TestCases/Posix/posix_memalign-alignment.cc20
-rw-r--r--compiler-rt/test/asan/TestCases/Windows/oom.cc2
-rw-r--r--compiler-rt/test/asan/TestCases/allocator_returns_null.cc18
-rw-r--r--compiler-rt/test/asan/TestCases/calloc-overflow.cc19
-rw-r--r--compiler-rt/test/asan/TestCases/malloc-size-too-big.cc26
-rw-r--r--compiler-rt/test/lsan/TestCases/allocator_returns_null.cc22
-rw-r--r--compiler-rt/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc2
18 files changed, 455 insertions, 51 deletions
diff --git a/compiler-rt/lib/asan/asan_allocator.cc b/compiler-rt/lib/asan/asan_allocator.cc
index ee8af9758b4..b8f7eb5741c 100644
--- a/compiler-rt/lib/asan/asan_allocator.cc
+++ b/compiler-rt/lib/asan/asan_allocator.cc
@@ -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(uptr addr) {
}
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, BufferedStackTrace *stack) {
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 size, BufferedStackTrace *stack,
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 size, BufferedStackTrace *stack,
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(const void *p) {
}
void __sanitizer_purge_allocator() {
- instance.Purge();
+ GET_STACK_TRACE_MALLOC;
+ instance.Purge(&stack);
}
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
diff --git a/compiler-rt/lib/asan/asan_errors.cc b/compiler-rt/lib/asan/asan_errors.cc
index 0f4a3abff9a..02e243b127c 100644
--- a/compiler-rt/lib/asan/asan_errors.cc
+++ b/compiler-rt/lib/asan/asan_errors.cc
@@ -172,6 +172,106 @@ void ErrorSanitizerGetAllocatedSizeNotOwned::Print() {
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];
diff --git a/compiler-rt/lib/asan/asan_errors.h b/compiler-rt/lib/asan/asan_errors.h
index 518ba0c6945..7d55c55a63d 100644
--- a/compiler-rt/lib/asan/asan_errors.h
+++ b/compiler-rt/lib/asan/asan_errors.h
@@ -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 ErrorSanitizerGetAllocatedSizeNotOwned : ErrorBase {
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) \
diff --git a/compiler-rt/lib/asan/asan_new_delete.cc b/compiler-rt/lib/asan/asan_new_delete.cc
index 072f027addd..0c8c9e97776 100644
--- a/compiler-rt/lib/asan/asan_new_delete.cc
+++ b/compiler-rt/lib/asan/asan_new_delete.cc
@@ -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
diff --git a/compiler-rt/lib/asan/asan_report.cc b/compiler-rt/lib/asan/asan_report.cc
index 3d0e88157a7..7c827c6a135 100644
--- a/compiler-rt/lib/asan/asan_report.cc
+++ b/compiler-rt/lib/asan/asan_report.cc
@@ -254,6 +254,54 @@ void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
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,
diff --git a/compiler-rt/lib/asan/asan_report.h b/compiler-rt/lib/asan/asan_report.h
index f2cdad47ee8..e484ca90bfc 100644
--- a/compiler-rt/lib/asan/asan_report.h
+++ b/compiler-rt/lib/asan/asan_report.h
@@ -58,6 +58,16 @@ void ReportAllocTypeMismatch(uptr addr, BufferedStackTrace *free_stack,
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,
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc
index 0642ee426da..61a671d149b 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc
@@ -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
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h
index 38368361de6..8c6bb3968d2 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h
@@ -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 {
diff --git a/compiler-rt/test/asan/TestCases/Linux/aligned_alloc-alignment.cc b/compiler-rt/test/asan/TestCases/Linux/aligned_alloc-alignment.cc
new file mode 100644
index 00000000000..618aa8af7df
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Linux/aligned_alloc-alignment.cc
@@ -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;
+}
diff --git a/compiler-rt/test/asan/TestCases/Linux/allocator_oom_test.cc b/compiler-rt/test/asan/TestCases/Linux/allocator_oom_test.cc
index 6382003781c..69ca07d6d82 100644
--- a/compiler-rt/test/asan/TestCases/Linux/allocator_oom_test.cc
+++ b/compiler-rt/test/asan/TestCases/Linux/allocator_oom_test.cc
@@ -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
diff --git a/compiler-rt/test/asan/TestCases/Linux/pvalloc-overflow.cc b/compiler-rt/test/asan/TestCases/Linux/pvalloc-overflow.cc
index b47c6266b93..1d40811fc87 100644
--- a/compiler-rt/test/asan/TestCases/Linux/pvalloc-overflow.cc
+++ b/compiler-rt/test/asan/TestCases/Linux/pvalloc-overflow.cc
@@ -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
diff --git a/compiler-rt/test/asan/TestCases/Posix/posix_memalign-alignment.cc b/compiler-rt/test/asan/TestCases/Posix/posix_memalign-alignment.cc
new file mode 100644
index 00000000000..208772d9fbc
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Posix/posix_memalign-alignment.cc
@@ -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;
+}
diff --git a/compiler-rt/test/asan/TestCases/Windows/oom.cc b/compiler-rt/test/asan/TestCases/Windows/oom.cc
index 71a9c2a759a..4d68c145eca 100644
--- a/compiler-rt/test/asan/TestCases/Windows/oom.cc
+++ b/compiler-rt/test/asan/TestCases/Windows/oom.cc
@@ -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
}
diff --git a/compiler-rt/test/asan/TestCases/allocator_returns_null.cc b/compiler-rt/test/asan/TestCases/allocator_returns_null.cc
index 8ce002f04d6..7d4a9686663 100644
--- a/compiler-rt/test/asan/TestCases/allocator_returns_null.cc
+++ b/compiler-rt/test/asan/TestCases/allocator_returns_null.cc
@@ -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
diff --git a/compiler-rt/test/asan/TestCases/calloc-overflow.cc b/compiler-rt/test/asan/TestCases/calloc-overflow.cc
new file mode 100644
index 00000000000..65278101c8d
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/calloc-overflow.cc
@@ -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;
+}
diff --git a/compiler-rt/test/asan/TestCases/malloc-size-too-big.cc b/compiler-rt/test/asan/TestCases/malloc-size-too-big.cc
new file mode 100644
index 00000000000..f48d8a7f8ff
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/malloc-size-too-big.cc
@@ -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;
+}
diff --git a/compiler-rt/test/lsan/TestCases/allocator_returns_null.cc b/compiler-rt/test/lsan/TestCases/allocator_returns_null.cc
index 28dd696dc67..722cc5c4e18 100644
--- a/compiler-rt/test/lsan/TestCases/allocator_returns_null.cc
+++ b/compiler-rt/test/lsan/TestCases/allocator_returns_null.cc
@@ -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
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc b/compiler-rt/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc
index 2ee80954753..4c373f15355 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc
+++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc
@@ -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}}
OpenPOWER on IntegriCloud