Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[LSan] Report proper error on allocator failures instead of CHECK(0)-ing
Summary: Following up on and complementing D44404. Currently many allocator specific errors (OOM, for example) are reported as a text message and CHECK(0) termination, not stack, no details, not too helpful nor informative. To improve the situation, detailed and structured errors were defined and reported under the appropriate conditions. Reviewers: eugenis Subscribers: srhines, mgorny, delcypher, llvm-commits, #sanitizers Differential Revision: https://reviews.llvm.org/D47645 llvm-svn: 334034
- Loading branch information
1 parent
89f5293
commit 236c3f9
Showing
10 changed files
with
275 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
126 changes: 126 additions & 0 deletions
126
compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
//===-- sanitizer_allocator_report.cc ---------------------------*- C++ -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
/// | ||
/// \file | ||
/// Shared allocator error reporting for ThreadSanitizer, MemorySanitizer, etc. | ||
/// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "sanitizer_allocator.h" | ||
#include "sanitizer_allocator_report.h" | ||
#include "sanitizer_common.h" | ||
#include "sanitizer_report_decorator.h" | ||
|
||
namespace __sanitizer { | ||
|
||
class ScopedAllocatorErrorReport { | ||
public: | ||
ScopedAllocatorErrorReport(const char *error_summary_, | ||
const StackTrace *stack_) | ||
: error_summary(error_summary_), | ||
stack(stack_) { | ||
Printf("%s", d.Error()); | ||
} | ||
~ScopedAllocatorErrorReport() { | ||
Printf("%s", d.Default()); | ||
stack->Print(); | ||
// TODO(alekseyshl): Define SanitizerToolOptionsEnvVarName and use it there. | ||
PrintHintAllocatorCannotReturnNull(""); | ||
ReportErrorSummary(error_summary, stack); | ||
} | ||
|
||
private: | ||
ScopedErrorReportLock lock; | ||
const char *error_summary; | ||
const StackTrace* const stack; | ||
const SanitizerCommonDecorator d; | ||
}; | ||
|
||
void NORETURN ReportCallocOverflow(uptr count, uptr size, | ||
const StackTrace *stack) { | ||
{ | ||
ScopedAllocatorErrorReport report("calloc-overflow", stack); | ||
Report("ERROR: %s: calloc parameters overflow: count * size (%zd * %zd) " | ||
"cannot be represented in type size_t\n", SanitizerToolName, count, | ||
size); | ||
} | ||
Die(); | ||
} | ||
|
||
void NORETURN ReportPvallocOverflow(uptr size, const StackTrace *stack) { | ||
{ | ||
ScopedAllocatorErrorReport report("pvalloc-overflow", stack); | ||
Report("ERROR: %s: pvalloc parameters overflow: size 0x%zx rounded up to " | ||
"system page size 0x%zx cannot be represented in type size_t\n", | ||
SanitizerToolName, size, GetPageSizeCached()); | ||
} | ||
Die(); | ||
} | ||
|
||
void NORETURN ReportInvalidAllocationAlignment(uptr alignment, | ||
const StackTrace *stack) { | ||
{ | ||
ScopedAllocatorErrorReport report("invalid-allocation-alignment", stack); | ||
Report("ERROR: %s: invalid allocation alignment: %zd, alignment must be a " | ||
"power of two\n", SanitizerToolName, alignment); | ||
} | ||
Die(); | ||
} | ||
|
||
void NORETURN ReportInvalidAlignedAllocAlignment(uptr size, uptr alignment, | ||
const StackTrace *stack) { | ||
{ | ||
ScopedAllocatorErrorReport report("invalid-aligned-alloc-alignment", stack); | ||
#if SANITIZER_POSIX | ||
Report("ERROR: %s: invalid alignment requested in " | ||
"aligned_alloc: %zd, alignment must be a power of two and the " | ||
"requested size 0x%zx must be a multiple of alignment\n", | ||
SanitizerToolName, alignment, size); | ||
#else | ||
Report("ERROR: %s: invalid alignment requested in aligned_alloc: %zd, " | ||
"the requested size 0x%zx must be a multiple of alignment\n", | ||
SanitizerToolName, alignment, size); | ||
#endif | ||
} | ||
Die(); | ||
} | ||
|
||
void NORETURN ReportInvalidPosixMemalignAlignment(uptr alignment, | ||
const StackTrace *stack) { | ||
{ | ||
ScopedAllocatorErrorReport report("invalid-posix-memalign-alignment", | ||
stack); | ||
Report("ERROR: %s: invalid alignment requested in " | ||
"posix_memalign: %zd, alignment must be a power of two and a " | ||
"multiple of sizeof(void*) == %zd\n", SanitizerToolName, alignment, | ||
sizeof(void*)); // NOLINT | ||
} | ||
Die(); | ||
} | ||
|
||
void NORETURN ReportAllocationSizeTooBig(uptr user_size, uptr max_size, | ||
const StackTrace *stack) { | ||
{ | ||
ScopedAllocatorErrorReport report("allocation-size-too-big", stack); | ||
Report("ERROR: %s: requested allocation size 0x%zx exceeds maximum " | ||
"supported size of 0x%zx\n", SanitizerToolName, user_size, max_size); | ||
} | ||
Die(); | ||
} | ||
|
||
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); | ||
} | ||
Die(); | ||
} | ||
|
||
} // namespace __sanitizer |
38 changes: 38 additions & 0 deletions
38
compiler-rt/lib/sanitizer_common/sanitizer_allocator_report.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
//===-- sanitizer_allocator_report.h ----------------------------*- C++ -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
/// | ||
/// \file | ||
/// Shared allocator error reporting for ThreadSanitizer, MemorySanitizer, etc. | ||
/// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef SANITIZER_ALLOCATOR_REPORT_H | ||
#define SANITIZER_ALLOCATOR_REPORT_H | ||
|
||
#include "sanitizer_internal_defs.h" | ||
#include "sanitizer_stacktrace.h" | ||
|
||
namespace __sanitizer { | ||
|
||
void NORETURN ReportCallocOverflow(uptr count, uptr size, | ||
const StackTrace *stack); | ||
void NORETURN ReportPvallocOverflow(uptr size, const StackTrace *stack); | ||
void NORETURN ReportInvalidAllocationAlignment(uptr alignment, | ||
const StackTrace *stack); | ||
void NORETURN ReportInvalidAlignedAllocAlignment(uptr size, uptr alignment, | ||
const StackTrace *stack); | ||
void NORETURN ReportInvalidPosixMemalignAlignment(uptr alignment, | ||
const StackTrace *stack); | ||
void NORETURN ReportAllocationSizeTooBig(uptr user_size, uptr max_size, | ||
const StackTrace *stack); | ||
void NORETURN ReportOutOfMemory(uptr requested_size, const StackTrace *stack); | ||
|
||
} // namespace __sanitizer | ||
|
||
#endif // SANITIZER_ALLOCATOR_REPORT_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
compiler-rt/test/lsan/TestCases/Linux/aligned_alloc-alignment.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// RUN: %clangxx_lsan -O0 %s -o %t | ||
// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s | ||
// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL | ||
|
||
// UNSUPPORTED: android | ||
|
||
// REQUIRES: stable-runtime | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
extern void *aligned_alloc(size_t alignment, size_t size); | ||
|
||
int main() { | ||
void *p = aligned_alloc(17, 100); | ||
// CHECK: {{ERROR: .*Sanitizer: invalid allocation alignment: 17}} | ||
// CHECK: {{#0 0x.* in .*}}{{aligned_alloc|memalign}} | ||
// CHECK: {{#1 0x.* in main .*aligned_alloc-alignment.cc:}}[[@LINE-3]] | ||
// CHECK: {{SUMMARY: .*Sanitizer: invalid-allocation-alignment}} | ||
|
||
printf("pointer after failed aligned_alloc: %zd\n", (size_t)p); | ||
// CHECK-NULL: pointer after failed aligned_alloc: 0 | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
def getRoot(config): | ||
if not config.parent: | ||
return config | ||
return getRoot(config.parent) | ||
|
||
root = getRoot(config) | ||
|
||
if root.host_os in ['Windows']: | ||
config.unsupported = True |
22 changes: 22 additions & 0 deletions
22
compiler-rt/test/lsan/TestCases/Posix/posix_memalign-alignment.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// RUN: %clangxx_lsan -O0 %s -o %t | ||
// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s | ||
// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL | ||
|
||
// REQUIRES: stable-runtime | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
int main() { | ||
void *p = reinterpret_cast<void*>(42); | ||
int res = posix_memalign(&p, 17, 100); | ||
// CHECK: {{ERROR: .*Sanitizer: 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: .*Sanitizer: 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; | ||
} |
Oops, something went wrong.