Index: lib/asan/asan_allocator.cc =================================================================== --- lib/asan/asan_allocator.cc +++ lib/asan/asan_allocator.cc @@ -134,8 +134,9 @@ }; 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 @@ 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 @@ get_allocator().Deallocate(cache_, p); } - AllocatorCache *cache_; + private: + AllocatorCache* const cache_; + BufferedStackTrace* const stack_; }; typedef Quarantine AsanQuarantine; @@ -397,8 +400,11 @@ 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 @@ } 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ } void AsanThreadLocalMallocStorage::CommitBack() { - instance.CommitBack(this); + GET_STACK_TRACE_MALLOC; + instance.CommitBack(this, &stack); } void PrintInternalAllocatorStats() { @@ -883,7 +903,9 @@ 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 @@ 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 @@ 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 @@ } void __sanitizer_purge_allocator() { - instance.Purge(); + GET_STACK_TRACE_MALLOC; + instance.Purge(&stack); } #if !SANITIZER_SUPPORTS_WEAK_HOOKS Index: lib/asan/asan_errors.h =================================================================== --- lib/asan/asan_errors.h +++ lib/asan/asan_errors.h @@ -23,6 +23,10 @@ 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 @@ 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 @@ 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) \ Index: lib/asan/asan_errors.cc =================================================================== --- lib/asan/asan_errors.cc +++ lib/asan/asan_errors.cc @@ -172,6 +172,106 @@ 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]; Index: lib/asan/asan_new_delete.cc =================================================================== --- lib/asan/asan_new_delete.cc +++ 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" @@ -71,12 +72,16 @@ #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)) {\ + SetAllocatorOutOfMemory(); 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)) {\ + SetAllocatorOutOfMemory(); ReportOutOfMemory(size, &stack);\ + }\ return res; // On OS X it's not enough to just provide our own 'operator new' and Index: lib/asan/asan_report.h =================================================================== --- lib/asan/asan_report.h +++ lib/asan/asan_report.h @@ -58,6 +58,16 @@ 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, Index: lib/asan/asan_report.cc =================================================================== --- lib/asan/asan_report.cc +++ lib/asan/asan_report.cc @@ -254,6 +254,54 @@ 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, Index: lib/sanitizer_common/sanitizer_allocator.h =================================================================== --- lib/sanitizer_common/sanitizer_allocator.h +++ lib/sanitizer_common/sanitizer_allocator.h @@ -43,9 +43,12 @@ 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 { Index: lib/sanitizer_common/sanitizer_allocator.cc =================================================================== --- lib/sanitizer_common/sanitizer_allocator.cc +++ lib/sanitizer_common/sanitizer_allocator.cc @@ -218,6 +218,10 @@ 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 @@ 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 Index: test/asan/TestCases/Linux/aligned_alloc-alignment.cc =================================================================== --- /dev/null +++ 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 +#include + +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; +} Index: test/asan/TestCases/Linux/allocator_oom_test.cc =================================================================== --- test/asan/TestCases/Linux/allocator_oom_test.cc +++ test/asan/TestCases/Linux/allocator_oom_test.cc @@ -84,5 +84,5 @@ // 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 Index: test/asan/TestCases/Linux/pvalloc-overflow.cc =================================================================== --- test/asan/TestCases/Linux/pvalloc-overflow.cc +++ test/asan/TestCases/Linux/pvalloc-overflow.cc @@ -38,4 +38,7 @@ 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 Index: test/asan/TestCases/Posix/posix_memalign-alignment.cc =================================================================== --- /dev/null +++ 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 +#include + +int main() { + void *p = reinterpret_cast(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; +} Index: test/asan/TestCases/Windows/oom.cc =================================================================== --- test/asan/TestCases/Windows/oom.cc +++ test/asan/TestCases/Windows/oom.cc @@ -8,5 +8,5 @@ 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 } Index: test/asan/TestCases/allocator_returns_null.cc =================================================================== --- test/asan/TestCases/allocator_returns_null.cc +++ 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 @@ } // 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 Index: test/asan/TestCases/calloc-overflow.cc =================================================================== --- /dev/null +++ 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 +#include + +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; +} Index: test/asan/TestCases/malloc-size-too-big.cc =================================================================== --- /dev/null +++ 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 +#include + +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; +} Index: test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc =================================================================== --- test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc +++ test/sanitizer_common/TestCases/Linux/soft_rss_limit_mb_test.cc @@ -65,4 +65,4 @@ // 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}}