[compiler-rt] r334338 - [MSan] Report proper error on allocator failures instead of CHECK(0)-ing

Alex Shlyapnikov via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 8 16:31:42 PDT 2018


Author: alekseyshl
Date: Fri Jun  8 16:31:42 2018
New Revision: 334338

URL: http://llvm.org/viewvc/llvm-project?rev=334338&view=rev
Log:
[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

Added:
    compiler-rt/trunk/lib/msan/msan_report.h
    compiler-rt/trunk/test/msan/Linux/aligned_alloc-alignment.cc
    compiler-rt/trunk/test/msan/posix_memalign-alignment.cc
Modified:
    compiler-rt/trunk/lib/msan/msan.cc
    compiler-rt/trunk/lib/msan/msan.h
    compiler-rt/trunk/lib/msan/msan_allocator.cc
    compiler-rt/trunk/lib/msan/msan_interceptors.cc
    compiler-rt/trunk/lib/msan/msan_linux.cc
    compiler-rt/trunk/lib/msan/msan_new_delete.cc
    compiler-rt/trunk/lib/msan/msan_report.cc
    compiler-rt/trunk/test/msan/allocator_returns_null.cc
    compiler-rt/trunk/test/msan/pvalloc.cc

Modified: compiler-rt/trunk/lib/msan/msan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=334338&r1=334337&r2=334338&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan.cc (original)
+++ compiler-rt/trunk/lib/msan/msan.cc Fri Jun  8 16:31:42 2018
@@ -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"

Modified: compiler-rt/trunk/lib/msan/msan.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.h?rev=334338&r1=334337&r2=334338&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan.h (original)
+++ compiler-rt/trunk/lib/msan/msan.h Fri Jun  8 16:31:42 2018
@@ -316,14 +316,6 @@ void PrintWarningWithOrigin(uptr pc, upt
 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();

Modified: compiler-rt/trunk/lib/msan/msan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_allocator.cc?rev=334338&r1=334337&r2=334338&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_allocator.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_allocator.cc Fri Jun  8 16:31:42 2018
@@ -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::Commi
 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 *st
     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,
   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
 }
 
 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
   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
 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,
 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
 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;

Modified: compiler-rt/trunk/lib/msan/msan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_interceptors.cc?rev=334338&r1=334337&r2=334338&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_interceptors.cc Fri Jun  8 16:31:42 2018
@@ -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"

Modified: compiler-rt/trunk/lib/msan/msan_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_linux.cc?rev=334338&r1=334337&r2=334338&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_linux.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_linux.cc Fri Jun  8 16:31:42 2018
@@ -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>

Modified: compiler-rt/trunk/lib/msan/msan_new_delete.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_new_delete.cc?rev=334338&r1=334337&r2=334338&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_new_delete.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_new_delete.cc Fri Jun  8 16:31:42 2018
@@ -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

Modified: compiler-rt/trunk/lib/msan/msan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_report.cc?rev=334338&r1=334337&r2=334338&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_report.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_report.cc Fri Jun  8 16:31:42 2018
@@ -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) {

Added: compiler-rt/trunk/lib/msan/msan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_report.h?rev=334338&view=auto
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_report.h (added)
+++ compiler-rt/trunk/lib/msan/msan_report.h Fri Jun  8 16:31:42 2018
@@ -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

Added: compiler-rt/trunk/test/msan/Linux/aligned_alloc-alignment.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/Linux/aligned_alloc-alignment.cc?rev=334338&view=auto
==============================================================================
--- compiler-rt/trunk/test/msan/Linux/aligned_alloc-alignment.cc (added)
+++ compiler-rt/trunk/test/msan/Linux/aligned_alloc-alignment.cc Fri Jun  8 16:31:42 2018
@@ -0,0 +1,26 @@
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 -g %s -o %t
+// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
+// RUN: MSAN_OPTIONS=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: MemorySanitizer: invalid alignment requested in aligned_alloc: 17
+  // Check just the top frame since mips is forced to use store_context_size==1
+  // and also handle a case when aligned_alloc is aliased by memalign.
+  // CHECK: {{#0 0x.* in .*}}{{aligned_alloc|memalign}}
+  // CHECK: SUMMARY: MemorySanitizer: invalid-aligned-alloc-alignment
+
+  printf("pointer after failed aligned_alloc: %zd\n", (size_t)p);
+  // CHECK-NULL: pointer after failed aligned_alloc: 0
+
+  return 0;
+}

Modified: compiler-rt/trunk/test/msan/allocator_returns_null.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/allocator_returns_null.cc?rev=334338&r1=334337&r2=334338&view=diff
==============================================================================
--- compiler-rt/trunk/test/msan/allocator_returns_null.cc (original)
+++ compiler-rt/trunk/test/msan/allocator_returns_null.cc Fri Jun  8 16:31:42 2018
@@ -30,7 +30,7 @@
 // RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t new 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=CHECK-nCRASH
 // RUN: MSAN_OPTIONS=allocator_may_return_null=1 not %run %t new 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-nCRASH
+// RUN:   | FileCheck %s --check-prefix=CHECK-nCRASH-OOM
 // RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=CHECK-nnCRASH
 // RUN: MSAN_OPTIONS=allocator_may_return_null=1     %run %t new-nothrow 2>&1 \
@@ -98,19 +98,21 @@ int main(int argc, char **argv) {
 }
 
 // CHECK-mCRASH: malloc:
-// CHECK-mCRASH: MemorySanitizer's allocator is terminating the process
+// CHECK-mCRASH: SUMMARY: MemorySanitizer: allocation-size-too-big
 // CHECK-cCRASH: calloc:
-// CHECK-cCRASH: MemorySanitizer's allocator is terminating the process
+// CHECK-cCRASH: SUMMARY: MemorySanitizer: allocation-size-too-big
 // CHECK-coCRASH: calloc-overflow:
-// CHECK-coCRASH: MemorySanitizer's allocator is terminating the process
+// CHECK-coCRASH: SUMMARY: MemorySanitizer: calloc-overflow
 // CHECK-rCRASH: realloc:
-// CHECK-rCRASH: MemorySanitizer's allocator is terminating the process
+// CHECK-rCRASH: SUMMARY: MemorySanitizer: allocation-size-too-big
 // CHECK-mrCRASH: realloc-after-malloc:
-// CHECK-mrCRASH: MemorySanitizer's allocator is terminating the process
+// CHECK-mrCRASH: SUMMARY: MemorySanitizer: allocation-size-too-big
 // CHECK-nCRASH: new:
-// CHECK-nCRASH: MemorySanitizer's allocator is terminating the process
+// CHECK-nCRASH: SUMMARY: MemorySanitizer: allocation-size-too-big
+// CHECK-nCRASH-OOM: new:
+// CHECK-nCRASH-OOM: SUMMARY: MemorySanitizer: out-of-memory
 // CHECK-nnCRASH: new-nothrow:
-// CHECK-nnCRASH: MemorySanitizer's allocator is terminating the process
+// CHECK-nnCRASH: SUMMARY: MemorySanitizer: allocation-size-too-big
 
 // CHECK-mNULL: malloc:
 // CHECK-mNULL: errno: 12

Added: compiler-rt/trunk/test/msan/posix_memalign-alignment.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/posix_memalign-alignment.cc?rev=334338&view=auto
==============================================================================
--- compiler-rt/trunk/test/msan/posix_memalign-alignment.cc (added)
+++ compiler-rt/trunk/test/msan/posix_memalign-alignment.cc Fri Jun  8 16:31:42 2018
@@ -0,0 +1,22 @@
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 -g %s -o %t
+// RUN: MSAN_OPTIONS=$MSAN_OPTIONS:allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
+// RUN: MSAN_OPTIONS=$MSAN_OPTIONS: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: MemorySanitizer: invalid alignment requested in posix_memalign: 17
+  // Check just the top frame since mips is forced to use store_context_size==1
+  // CHECK: {{#0 0x.* in .*posix_memalign}}
+  // CHECK: SUMMARY: MemorySanitizer: 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;
+}

Modified: compiler-rt/trunk/test/msan/pvalloc.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/pvalloc.cc?rev=334338&r1=334337&r2=334338&view=diff
==============================================================================
--- compiler-rt/trunk/test/msan/pvalloc.cc (original)
+++ compiler-rt/trunk/test/msan/pvalloc.cc Fri Jun  8 16:31:42 2018
@@ -1,4 +1,4 @@
-// RUN: %clangxx_msan -O0 %s -o %t
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 -g %s -o %t
 // RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t m1 2>&1 | FileCheck %s
 // RUN: MSAN_OPTIONS=allocator_may_return_null=1     %run %t m1 2>&1
 // RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t psm1 2>&1 | FileCheck %s
@@ -41,4 +41,6 @@ int main(int argc, char *argv[]) {
   return 0;
 }
 
-// CHECK: MemorySanitizer's allocator is terminating the process
+// CHECK: {{ERROR: MemorySanitizer: pvalloc parameters overflow: size .* rounded up to system page size .* cannot be represented in type size_t}}
+// CHECK: {{#0 0x.* in .*pvalloc}}
+// CHECK: SUMMARY: MemorySanitizer: pvalloc-overflow




More information about the llvm-commits mailing list