diff options
Diffstat (limited to 'lib/sanitizer_common/sanitizer_allocator.cc')
-rw-r--r-- | lib/sanitizer_common/sanitizer_allocator.cc | 64 |
1 files changed, 30 insertions, 34 deletions
diff --git a/lib/sanitizer_common/sanitizer_allocator.cc b/lib/sanitizer_common/sanitizer_allocator.cc index fc4f7a75ae34..6bfd5e5eea50 100644 --- a/lib/sanitizer_common/sanitizer_allocator.cc +++ b/lib/sanitizer_common/sanitizer_allocator.cc @@ -21,6 +21,10 @@ namespace __sanitizer { +// Default allocator names. +const char *PrimaryAllocatorName = "SizeClassAllocator"; +const char *SecondaryAllocatorName = "LargeMmapAllocator"; + // ThreadSanitizer for Go uses libc malloc/free. #if SANITIZER_GO || defined(SANITIZER_USE_MALLOC) # if SANITIZER_LINUX && !SANITIZER_ANDROID @@ -136,12 +140,19 @@ static void RawInternalFree(void *ptr, InternalAllocatorCache *cache) { const u64 kBlockMagic = 0x6A6CB03ABCEBC041ull; +static void NORETURN ReportInternalAllocatorOutOfMemory(uptr requested_size) { + SetAllocatorOutOfMemory(); + Report("FATAL: %s: internal allocator is out of memory trying to allocate " + "0x%zx bytes\n", SanitizerToolName, requested_size); + Die(); +} + void *InternalAlloc(uptr size, InternalAllocatorCache *cache, uptr alignment) { if (size + sizeof(u64) < size) return nullptr; void *p = RawInternalAlloc(size + sizeof(u64), cache, alignment); - if (!p) - return nullptr; + if (UNLIKELY(!p)) + ReportInternalAllocatorOutOfMemory(size + sizeof(u64)); ((u64*)p)[0] = kBlockMagic; return (char*)p + sizeof(u64); } @@ -155,16 +166,21 @@ void *InternalRealloc(void *addr, uptr size, InternalAllocatorCache *cache) { size = size + sizeof(u64); CHECK_EQ(kBlockMagic, ((u64*)addr)[0]); void *p = RawInternalRealloc(addr, size, cache); - if (!p) - return nullptr; + if (UNLIKELY(!p)) + ReportInternalAllocatorOutOfMemory(size); return (char*)p + sizeof(u64); } void *InternalCalloc(uptr count, uptr size, InternalAllocatorCache *cache) { - if (UNLIKELY(CheckForCallocOverflow(count, size))) - return InternalAllocator::FailureHandler::OnBadRequest(); + if (UNLIKELY(CheckForCallocOverflow(count, size))) { + Report("FATAL: %s: calloc parameters overflow: count * size (%zd * %zd) " + "cannot be represented in type size_t\n", SanitizerToolName, count, + size); + Die(); + } void *p = InternalAlloc(count * size, cache); - if (p) internal_memset(p, 0, count * size); + if (LIKELY(p)) + internal_memset(p, 0, count * size); return p; } @@ -210,6 +226,8 @@ void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback) { low_level_alloc_callback = callback; } +// Allocator's OOM and other errors handling support. + static atomic_uint8_t allocator_out_of_memory = {0}; static atomic_uint8_t allocator_may_return_null = {0}; @@ -217,13 +235,8 @@ bool IsAllocatorOutOfMemory() { return atomic_load_relaxed(&allocator_out_of_memory); } -// Prints error message and kills the program. -void NORETURN ReportAllocatorCannotReturnNull() { - Report("%s's allocator is terminating the process instead of returning 0\n", - SanitizerToolName); - Report("If you don't like this behavior set allocator_may_return_null=1\n"); - CHECK(0); - Die(); +void SetAllocatorOutOfMemory() { + atomic_store_relaxed(&allocator_out_of_memory, 1); } bool AllocatorMayReturnNull() { @@ -235,26 +248,9 @@ void SetAllocatorMayReturnNull(bool may_return_null) { memory_order_relaxed); } -void *ReturnNullOrDieOnFailure::OnBadRequest() { - if (AllocatorMayReturnNull()) - return nullptr; - ReportAllocatorCannotReturnNull(); -} - -void *ReturnNullOrDieOnFailure::OnOOM() { - atomic_store_relaxed(&allocator_out_of_memory, 1); - if (AllocatorMayReturnNull()) - return nullptr; - ReportAllocatorCannotReturnNull(); -} - -void NORETURN *DieOnFailure::OnBadRequest() { - ReportAllocatorCannotReturnNull(); -} - -void NORETURN *DieOnFailure::OnOOM() { - atomic_store_relaxed(&allocator_out_of_memory, 1); - ReportAllocatorCannotReturnNull(); +void PrintHintAllocatorCannotReturnNull() { + Report("HINT: if you don't care about these errors you may set " + "allocator_may_return_null=1\n"); } } // namespace __sanitizer |