From e1d84c421df1bd496918bc4dd30f040d47906a77 Mon Sep 17 00:00:00 2001 From: Leonard Chan Date: Tue, 7 Jun 2022 16:45:01 -0700 Subject: [PATCH] [compiler-rt][sanitizer] Have all OOM-related error messages start with the same format This way downstream tools that read sanitizer output can differentiate between OOM errors reported by sanitizers from other sanitizer errors. Changes: - Introduce ErrorIsOOM for checking if a platform-specific error code from an "mmap" is an OOM err. - Add ReportOOMError which just prepends this error message to the start of a Report call. - Replace some Reports for OOMs with calls to ReportOOMError. - Update necessary tests. Differential Revision: https://reviews.llvm.org/D127161 --- compiler-rt/lib/asan/asan_errors.cpp | 4 +--- .../sanitizer_common/sanitizer_allocator_report.cpp | 3 +-- .../lib/sanitizer_common/sanitizer_common.cpp | 12 +++++++++--- compiler-rt/lib/sanitizer_common/sanitizer_common.h | 12 ++++++++++++ .../lib/sanitizer_common/sanitizer_fuchsia.cpp | 2 ++ compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp | 2 ++ compiler-rt/lib/sanitizer_common/sanitizer_win.cpp | 5 +++++ compiler-rt/test/hwasan/TestCases/sizes.cpp | 2 +- compiler-rt/test/lsan/TestCases/realloc_too_big.c | 2 +- 9 files changed, 34 insertions(+), 10 deletions(-) diff --git a/compiler-rt/lib/asan/asan_errors.cpp b/compiler-rt/lib/asan/asan_errors.cpp index a22bf130d823..10f7c17991d7 100644 --- a/compiler-rt/lib/asan/asan_errors.cpp +++ b/compiler-rt/lib/asan/asan_errors.cpp @@ -279,9 +279,7 @@ void ErrorRssLimitExceeded::Print() { 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); + ERROR_OOM("allocator is 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 index 1c6520819ef9..129f925e6fb6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cpp @@ -128,8 +128,7 @@ void NORETURN ReportAllocationSizeTooBig(uptr user_size, uptr max_size, 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); + ERROR_OOM("allocator is trying to allocate 0x%zx bytes\n", requested_size); } Die(); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp index 0b7401f925f2..82236453157f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp @@ -46,9 +46,15 @@ void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, 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)) { + ERROR_OOM("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_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 9614883a9605..345c262af972 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -311,6 +311,18 @@ void NORETURN ReportMmapFailureAndDie(uptr size, const char *mem_type, 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 ERROR_OOM(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_fuchsia.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp index 848953a6ab00..d8cf93ecbeca 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp @@ -128,6 +128,8 @@ uptr GetMaxUserVirtualAddress() { 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 index 19dfaa9e4e01..b0e32b50c076 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp @@ -41,6 +41,8 @@ uptr GetMmapGranularity() { 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 index 53770331199f..c997514cfed7 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp @@ -131,6 +131,11 @@ void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, } #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 index 4a1156b91b5c..2cb70f52147a 100644 --- a/compiler-rt/test/hwasan/TestCases/sizes.cpp +++ b/compiler-rt/test/hwasan/TestCases/sizes.cpp @@ -84,6 +84,6 @@ int main(int argc, char **argv) { } // 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 trying to allocate // 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 index bb1316024b5c..9e71e7347523 100644 --- 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).