summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/asan/asan_errors.cc16
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc57
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_allocator.h20
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h7
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h8
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cc3
6 files changed, 43 insertions, 68 deletions
diff --git a/compiler-rt/lib/asan/asan_errors.cc b/compiler-rt/lib/asan/asan_errors.cc
index abbb8e6ce56..6943e67c5ca 100644
--- a/compiler-rt/lib/asan/asan_errors.cc
+++ b/compiler-rt/lib/asan/asan_errors.cc
@@ -182,7 +182,7 @@ void ErrorCallocOverflow::Print() {
count, size, tid, ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
Printf("%s", d.Default());
stack->Print();
- PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+ PrintHintAllocatorCannotReturnNull();
ReportErrorSummary(scariness.GetDescription(), stack);
}
@@ -198,7 +198,7 @@ void ErrorPvallocOverflow::Print() {
ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
Printf("%s", d.Default());
stack->Print();
- PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+ PrintHintAllocatorCannotReturnNull();
ReportErrorSummary(scariness.GetDescription(), stack);
}
@@ -212,7 +212,7 @@ void ErrorInvalidAllocationAlignment::Print() {
alignment, tid, ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
Printf("%s", d.Default());
stack->Print();
- PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+ PrintHintAllocatorCannotReturnNull();
ReportErrorSummary(scariness.GetDescription(), stack);
}
@@ -234,7 +234,7 @@ void ErrorInvalidAlignedAllocAlignment::Print() {
#endif
Printf("%s", d.Default());
stack->Print();
- PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+ PrintHintAllocatorCannotReturnNull();
ReportErrorSummary(scariness.GetDescription(), stack);
}
@@ -250,7 +250,7 @@ void ErrorInvalidPosixMemalignAlignment::Print() {
ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
Printf("%s", d.Default());
stack->Print();
- PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+ PrintHintAllocatorCannotReturnNull();
ReportErrorSummary(scariness.GetDescription(), stack);
}
@@ -266,7 +266,7 @@ void ErrorAllocationSizeTooBig::Print() {
ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
Printf("%s", d.Default());
stack->Print();
- PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+ PrintHintAllocatorCannotReturnNull();
ReportErrorSummary(scariness.GetDescription(), stack);
}
@@ -278,7 +278,7 @@ void ErrorRssLimitExceeded::Print() {
"soft_rss_limit_mb=%zd\n", common_flags()->soft_rss_limit_mb);
Printf("%s", d.Default());
stack->Print();
- PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+ PrintHintAllocatorCannotReturnNull();
ReportErrorSummary(scariness.GetDescription(), stack);
}
@@ -290,7 +290,7 @@ void ErrorOutOfMemory::Print() {
"0x%zx bytes\n", requested_size);
Printf("%s", d.Default());
stack->Print();
- PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+ PrintHintAllocatorCannotReturnNull();
ReportErrorSummary(scariness.GetDescription(), stack);
}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc
index 0fdaef17f87..6bfd5e5eea5 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc
@@ -140,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 (UNLIKELY(!p))
- return DieOnFailure::OnOOM();
+ ReportInternalAllocatorOutOfMemory(size + sizeof(u64));
((u64*)p)[0] = kBlockMagic;
return (char*)p + sizeof(u64);
}
@@ -160,13 +167,17 @@ void *InternalRealloc(void *addr, uptr size, InternalAllocatorCache *cache) {
CHECK_EQ(kBlockMagic, ((u64*)addr)[0]);
void *p = RawInternalRealloc(addr, size, cache);
if (UNLIKELY(!p))
- return DieOnFailure::OnOOM();
+ ReportInternalAllocatorOutOfMemory(size);
return (char*)p + sizeof(u64);
}
void *InternalCalloc(uptr count, uptr size, InternalAllocatorCache *cache) {
- if (UNLIKELY(CheckForCallocOverflow(count, size)))
- return DieOnFailure::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 (LIKELY(p))
internal_memset(p, 0, count * size);
@@ -215,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};
@@ -226,15 +239,6 @@ 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",
- SanitizerToolName);
- Report("If you don't like this behavior set allocator_may_return_null=1\n");
- CHECK(0);
- Die();
-}
-
bool AllocatorMayReturnNull() {
return atomic_load(&allocator_may_return_null, memory_order_relaxed);
}
@@ -244,32 +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();
-}
-
-// Prints hint message.
-void PrintHintAllocatorCannotReturnNull(const char *options_name) {
+void PrintHintAllocatorCannotReturnNull() {
Report("HINT: if you don't care about these errors you may set "
- "%s=allocator_may_return_null=1\n", options_name);
+ "allocator_may_return_null=1\n");
}
} // namespace __sanitizer
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h
index 0036f80a257..9655a2264f3 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h
@@ -34,26 +34,14 @@ extern const char *SecondaryAllocatorName;
bool AllocatorMayReturnNull();
void SetAllocatorMayReturnNull(bool may_return_null);
-// Allocator failure handling policies:
-// Implements AllocatorMayReturnNull policy, returns null when the flag is set,
-// dies otherwise.
-struct ReturnNullOrDieOnFailure {
- static void *OnBadRequest();
- static void *OnOOM();
-};
-// Always dies on the failure.
-struct DieOnFailure {
- static void NORETURN *OnBadRequest();
- 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.
+// hungry operations.
bool IsAllocatorOutOfMemory();
+// Should be called by a particular allocator when OOM is detected.
void SetAllocatorOutOfMemory();
+void PrintHintAllocatorCannotReturnNull();
+
// Allocators call these callbacks on mmap/munmap.
struct NoOpMapUnmapCallback {
void OnMap(uptr p, uptr size) const { }
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h
index 5bfe83b9ff9..1bb8fc27def 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_local_cache.h
@@ -260,8 +260,11 @@ struct SizeClassAllocator32LocalCache {
class_id, allocator, (TransferBatch *)c->batch[first_idx_to_drain]);
// Failure to allocate a batch while releasing memory is non recoverable.
// TODO(alekseys): Figure out how to do it without allocating a new batch.
- if (UNLIKELY(!b))
- DieOnFailure::OnOOM();
+ if (UNLIKELY(!b)) {
+ Report("FATAL: Internal error: %s's allocator failed to allocate a "
+ "transfer batch.\n", SanitizerToolName);
+ Die();
+ }
b->SetFromArray(&c->batch[first_idx_to_drain], count);
c->count -= count;
allocator->DeallocateBatch(&stats_, class_id, b);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
index 7a0ab5624b1..6acb4f8bc56 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
@@ -118,8 +118,12 @@ class SizeClassAllocator64 {
// Failure to allocate free array space while releasing memory is non
// recoverable.
if (UNLIKELY(!EnsureFreeArraySpace(region, region_beg,
- new_num_freed_chunks)))
- DieOnFailure::OnOOM();
+ new_num_freed_chunks))) {
+ Report("FATAL: Internal error: %s's allocator exhausted the free list "
+ "space for size class %zd (%zd bytes).\n", SanitizerToolName,
+ class_id, ClassIdToSize(class_id));
+ Die();
+ }
for (uptr i = 0; i < n_chunks; i++)
free_array[old_num_chunks + i] = chunks[i];
region->num_freed_chunks = new_num_freed_chunks;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cc b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cc
index 4760ba719fa..e93f90c2a4b 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cc
@@ -30,8 +30,7 @@ class ScopedAllocatorErrorReport {
~ScopedAllocatorErrorReport() {
Printf("%s", d.Default());
stack->Print();
- // TODO(alekseyshl): Define SanitizerToolOptionsEnvVarName and use it there.
- PrintHintAllocatorCannotReturnNull("");
+ PrintHintAllocatorCannotReturnNull();
ReportErrorSummary(error_summary, stack);
}
OpenPOWER on IntegriCloud