diff --git a/compiler-rt/lib/asan/asan_errors.cpp b/compiler-rt/lib/asan/asan_errors.cpp --- a/compiler-rt/lib/asan/asan_errors.cpp +++ b/compiler-rt/lib/asan/asan_errors.cpp @@ -279,9 +279,8 @@ void ErrorOutOfMemory::Print() { Decorator d; Printf("%s", d.Error()); - Report( - "ERROR: AddressSanitizer: allocator is out of memory trying to allocate " - "0x%zx bytes\n", requested_size); + ReportOOMError("allocator is out of memory trying to allocate 0x%zx bytes\n", + requested_size); Printf("%s", d.Default()); stack->Print(); PrintHintAllocatorCannotReturnNull(); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp @@ -128,8 +128,9 @@ void NORETURN ReportOutOfMemory(uptr requested_size, const StackTrace *stack) { { ScopedAllocatorErrorReport report("out-of-memory", stack); - Report("ERROR: %s: allocator is out of memory trying to allocate 0x%zx " - "bytes\n", SanitizerToolName, requested_size); + ReportOOMError( + "allocator is out of memory trying to allocate 0x%zx bytes\n", + requested_size); } Die(); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -311,6 +311,18 @@ const char *mmap_type, error_t err, bool raw_report = false); +// Returns true if the platform-specific error reported is an OOM error. +bool ErrorIsOOM(error_t err); + +// This reports an error in the form: +// +// `ERROR: {{SanitizerToolName}}: Out of Memory: {{err_msg}}` +// +// Downstream tools that read sanitizer output will know that errors starting +// in this format are specifically OOM errors. +#define ReportOOMError(err_msg, ...) \ + Report("ERROR: %s: Out of Memory: " err_msg, SanitizerToolName, __VA_ARGS__) + // Specific tools may override behavior of "Die" function to do tool-specific // job. typedef void (*DieCallbackType)(void); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp @@ -46,9 +46,15 @@ Die(); } recursion_count++; - Report("ERROR: %s failed to " - "%s 0x%zx (%zd) bytes of %s (error code: %d)\n", - SanitizerToolName, mmap_type, size, size, mem_type, err); + if (ErrorIsOOM(err)) { + ReportOOMError("failed to %s 0x%zx (%zd) bytes of %s (error code: %d)\n", + mmap_type, size, size, mem_type, err); + } else { + Report( + "ERROR: %s failed to " + "%s 0x%zx (%zd) bytes of %s (error code: %d)\n", + SanitizerToolName, mmap_type, size, size, mem_type, err); + } #if !SANITIZER_GO DumpProcessMap(); #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp @@ -128,6 +128,8 @@ uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); } +bool ErrorIsOOM(error_t err) { return err == ZX_ERR_NO_MEMORY; } + static void *DoAnonymousMmapOrDie(uptr size, const char *mem_type, bool raw_report, bool die_for_nomem) { size = RoundUpTo(size, GetPageSize()); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp @@ -41,6 +41,8 @@ return GetPageSize(); } +bool ErrorIsOOM(error_t err) { return err == ENOMEM; } + void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { size = RoundUpTo(size, GetPageSizeCached()); uptr res = MmapNamed(nullptr, size, PROT_READ | PROT_WRITE, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp @@ -131,6 +131,11 @@ } #endif // #if !SANITIZER_GO +bool ErrorIsOOM(error_t err) { + // TODO: This should check which `err`s correspond to OOM. + return false; +} + void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) { void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (rv == 0) diff --git a/compiler-rt/test/hwasan/TestCases/sizes.cpp b/compiler-rt/test/hwasan/TestCases/sizes.cpp --- a/compiler-rt/test/hwasan/TestCases/sizes.cpp +++ b/compiler-rt/test/hwasan/TestCases/sizes.cpp @@ -84,6 +84,6 @@ } // CHECK-max: {{ERROR: HWAddressSanitizer: requested allocation size .* exceeds maximum supported size}} -// CHECK-oom: ERROR: HWAddressSanitizer: allocator is out of memory +// CHECK-oom: ERROR: HWAddressSanitizer: Out of Memory: allocator is out of memory // CHECK-calloc: ERROR: HWAddressSanitizer: calloc parameters overflow // CHECK-reallocarray: ERROR: HWAddressSanitizer: reallocarray parameters overflow diff --git a/compiler-rt/test/lsan/TestCases/realloc_too_big.c b/compiler-rt/test/lsan/TestCases/realloc_too_big.c --- a/compiler-rt/test/lsan/TestCases/realloc_too_big.c +++ b/compiler-rt/test/lsan/TestCases/realloc_too_big.c @@ -8,7 +8,7 @@ #include #include -// CHECK: {{Leak|Address}}Sanitizer failed to allocate 0x100001 bytes +// CHECK: {{Leak|Address}}Sanitizer: Out of Memory: failed to allocate 0x100001 bytes // CHECK: {{Leak|Address}}Sanitizer: detected memory leaks // CHECK: {{Leak|Address}}Sanitizer: 9 byte(s) leaked in 1 allocation(s).