summaryrefslogtreecommitdiff
path: root/lib/msan
diff options
context:
space:
mode:
authorAlex Shlyapnikov <alekseys@google.com>2018-06-08 23:31:42 +0000
committerAlex Shlyapnikov <alekseys@google.com>2018-06-08 23:31:42 +0000
commitc6bb0cc2556bfcc55a1e01e522aa66600ad9c102 (patch)
treee9ed3ecfd82f72836b9e2efa9e792f7a6e5c0b7b /lib/msan
parentf8b77c7428db30e8b454b0e49081e280cb23095b (diff)
[MSan] 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, delcypher, #sanitizers, llvm-commits Differential Revision: https://reviews.llvm.org/D47793 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@334338 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/msan')
-rw-r--r--lib/msan/msan.cc1
-rw-r--r--lib/msan/msan.h8
-rw-r--r--lib/msan/msan_allocator.cc48
-rw-r--r--lib/msan/msan_interceptors.cc1
-rw-r--r--lib/msan/msan_linux.cc1
-rw-r--r--lib/msan/msan_new_delete.cc5
-rw-r--r--lib/msan/msan_report.cc5
-rw-r--r--lib/msan/msan_report.h34
8 files changed, 78 insertions, 25 deletions
diff --git a/lib/msan/msan.cc b/lib/msan/msan.cc
index c4e6a67f9..8bd2174aa 100644
--- a/lib/msan/msan.cc
+++ b/lib/msan/msan.cc
@@ -15,6 +15,7 @@
#include "msan.h"
#include "msan_chained_origin_depot.h"
#include "msan_origin.h"
+#include "msan_report.h"
#include "msan_thread.h"
#include "msan_poisoning.h"
#include "sanitizer_common/sanitizer_atomic.h"
diff --git a/lib/msan/msan.h b/lib/msan/msan.h
index ad1b86495..4c2e9f9e2 100644
--- a/lib/msan/msan.h
+++ b/lib/msan/msan.h
@@ -316,14 +316,6 @@ void PrintWarningWithOrigin(uptr pc, uptr bp, u32 origin);
void GetStackTrace(BufferedStackTrace *stack, uptr max_s, uptr pc, uptr bp,
void *context, bool request_fast_unwind);
-void ReportUMR(StackTrace *stack, u32 origin);
-void ReportExpectedUMRNotFound(StackTrace *stack);
-void ReportStats();
-void ReportAtExitStatistics();
-void DescribeMemoryRange(const void *x, uptr size);
-void ReportUMRInsideAddressRange(const char *what, const void *start, uptr size,
- uptr offset);
-
// Unpoison first n function arguments.
void UnpoisonParam(uptr n);
void UnpoisonThreadLocalState();
diff --git a/lib/msan/msan_allocator.cc b/lib/msan/msan_allocator.cc
index 8a23edf2c..3d03ca42c 100644
--- a/lib/msan/msan_allocator.cc
+++ b/lib/msan/msan_allocator.cc
@@ -15,6 +15,7 @@
#include "sanitizer_common/sanitizer_allocator.h"
#include "sanitizer_common/sanitizer_allocator_checks.h"
#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
#include "sanitizer_common/sanitizer_errno.h"
#include "msan.h"
#include "msan_allocator.h"
@@ -139,9 +140,11 @@ void MsanThreadLocalMallocStorage::CommitBack() {
static void *MsanAllocate(StackTrace *stack, uptr size, uptr alignment,
bool zeroise) {
if (size > kMaxAllowedMallocSize) {
- Report("WARNING: MemorySanitizer failed to allocate %p bytes\n",
- (void *)size);
- return ReturnNullOrDieOnFailure::OnBadRequest();
+ if (AllocatorMayReturnNull()) {
+ Report("WARNING: MemorySanitizer failed to allocate 0x%zx bytes\n", size);
+ return nullptr;
+ }
+ ReportAllocationSizeTooBig(size, kMaxAllowedMallocSize, stack);
}
MsanThread *t = GetCurrentThread();
void *allocated;
@@ -153,8 +156,12 @@ static void *MsanAllocate(StackTrace *stack, uptr size, uptr alignment,
AllocatorCache *cache = &fallback_allocator_cache;
allocated = allocator.Allocate(cache, size, alignment);
}
- if (UNLIKELY(!allocated))
- return ReturnNullOrDieOnFailure::OnOOM();
+ if (UNLIKELY(!allocated)) {
+ SetAllocatorOutOfMemory();
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportOutOfMemory(size, stack);
+ }
Metadata *meta =
reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated));
meta->requested_size = size;
@@ -224,6 +231,15 @@ void *MsanReallocate(StackTrace *stack, void *old_p, uptr new_size,
return new_p;
}
+void *MsanCalloc(StackTrace *stack, uptr nmemb, uptr size) {
+ if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportCallocOverflow(nmemb, size, stack);
+ }
+ return MsanAllocate(stack, nmemb * size, sizeof(u64), true);
+}
+
static uptr AllocationSize(const void *p) {
if (!p) return 0;
const void *beg = allocator.GetBlockBegin(p);
@@ -237,9 +253,7 @@ void *msan_malloc(uptr size, StackTrace *stack) {
}
void *msan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
- if (UNLIKELY(CheckForCallocOverflow(size, nmemb)))
- return SetErrnoOnNull(ReturnNullOrDieOnFailure::OnBadRequest());
- return SetErrnoOnNull(MsanAllocate(stack, nmemb * size, sizeof(u64), true));
+ return SetErrnoOnNull(MsanCalloc(stack, nmemb, size));
}
void *msan_realloc(void *ptr, uptr size, StackTrace *stack) {
@@ -260,7 +274,9 @@ void *msan_pvalloc(uptr size, StackTrace *stack) {
uptr PageSize = GetPageSizeCached();
if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) {
errno = errno_ENOMEM;
- return ReturnNullOrDieOnFailure::OnBadRequest();
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportPvallocOverflow(size, stack);
}
// pvalloc(0) should allocate one page.
size = size ? RoundUpTo(size, PageSize) : PageSize;
@@ -270,7 +286,9 @@ void *msan_pvalloc(uptr size, StackTrace *stack) {
void *msan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack) {
if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) {
errno = errno_EINVAL;
- return ReturnNullOrDieOnFailure::OnBadRequest();
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAlignedAllocAlignment(size, alignment, stack);
}
return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
}
@@ -278,7 +296,9 @@ void *msan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack) {
void *msan_memalign(uptr alignment, uptr size, StackTrace *stack) {
if (UNLIKELY(!IsPowerOfTwo(alignment))) {
errno = errno_EINVAL;
- return ReturnNullOrDieOnFailure::OnBadRequest();
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAllocationAlignment(alignment, stack);
}
return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
}
@@ -286,11 +306,13 @@ void *msan_memalign(uptr alignment, uptr size, StackTrace *stack) {
int msan_posix_memalign(void **memptr, uptr alignment, uptr size,
StackTrace *stack) {
if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
- ReturnNullOrDieOnFailure::OnBadRequest();
- return errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return errno_EINVAL;
+ ReportInvalidPosixMemalignAlignment(alignment, stack);
}
void *ptr = MsanAllocate(stack, size, alignment, false);
if (UNLIKELY(!ptr))
+ // OOM error is already taken care of by MsanAllocate.
return errno_ENOMEM;
CHECK(IsAligned((uptr)ptr, alignment));
*memptr = ptr;
diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc
index f0e9a258c..33fc63492 100644
--- a/lib/msan/msan_interceptors.cc
+++ b/lib/msan/msan_interceptors.cc
@@ -19,6 +19,7 @@
#include "msan.h"
#include "msan_chained_origin_depot.h"
#include "msan_origin.h"
+#include "msan_report.h"
#include "msan_thread.h"
#include "msan_poisoning.h"
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
diff --git a/lib/msan/msan_linux.cc b/lib/msan/msan_linux.cc
index 4e6321fcb..973e6620e 100644
--- a/lib/msan/msan_linux.cc
+++ b/lib/msan/msan_linux.cc
@@ -16,6 +16,7 @@
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
#include "msan.h"
+#include "msan_report.h"
#include "msan_thread.h"
#include <elf.h>
diff --git a/lib/msan/msan_new_delete.cc b/lib/msan/msan_new_delete.cc
index 5cc76e4bc..a0959aec5 100644
--- a/lib/msan/msan_new_delete.cc
+++ b/lib/msan/msan_new_delete.cc
@@ -15,6 +15,7 @@
#include "msan.h"
#include "interception/interception.h"
#include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
#if MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
@@ -33,12 +34,12 @@ namespace std {
#define OPERATOR_NEW_BODY(nothrow) \
GET_MALLOC_STACK_TRACE; \
void *res = msan_malloc(size, &stack);\
- if (!nothrow && UNLIKELY(!res)) DieOnFailure::OnOOM();\
+ if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
return res
#define OPERATOR_NEW_BODY_ALIGN(nothrow) \
GET_MALLOC_STACK_TRACE;\
void *res = msan_memalign((uptr)align, size, &stack);\
- if (!nothrow && UNLIKELY(!res)) DieOnFailure::OnOOM();\
+ if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
return res;
INTERCEPTOR_ATTRIBUTE
diff --git a/lib/msan/msan_report.cc b/lib/msan/msan_report.cc
index 28c9bbabb..2f0cc8d37 100644
--- a/lib/msan/msan_report.cc
+++ b/lib/msan/msan_report.cc
@@ -15,6 +15,7 @@
#include "msan.h"
#include "msan_chained_origin_depot.h"
#include "msan_origin.h"
+#include "msan_report.h"
#include "sanitizer_common/sanitizer_allocator_internal.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flags.h"
@@ -30,8 +31,8 @@ namespace __msan {
class Decorator: public __sanitizer::SanitizerCommonDecorator {
public:
Decorator() : SanitizerCommonDecorator() { }
- const char *Origin() { return Magenta(); }
- const char *Name() { return Green(); }
+ const char *Origin() const { return Magenta(); }
+ const char *Name() const { return Green(); }
};
static void DescribeStackOrigin(const char *so, uptr pc) {
diff --git a/lib/msan/msan_report.h b/lib/msan/msan_report.h
new file mode 100644
index 000000000..73840e417
--- /dev/null
+++ b/lib/msan/msan_report.h
@@ -0,0 +1,34 @@
+//===-- msan_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
+/// This file is a part of MemorySanitizer. MSan-private header for error
+/// reporting functions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef MSAN_REPORT_H
+#define MSAN_REPORT_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+#include "sanitizer_common/sanitizer_stacktrace.h"
+
+namespace __msan {
+
+void ReportUMR(StackTrace *stack, u32 origin);
+void ReportExpectedUMRNotFound(StackTrace *stack);
+void ReportStats();
+void ReportAtExitStatistics();
+void DescribeMemoryRange(const void *x, uptr size);
+void ReportUMRInsideAddressRange(const char *what, const void *start, uptr size,
+ uptr offset);
+
+} // namespace __msan
+
+#endif // MSAN_REPORT_H