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

Alex Shlyapnikov via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 18 13:03:31 PDT 2018


Author: alekseyshl
Date: Mon Jun 18 13:03:31 2018
New Revision: 334975

URL: http://llvm.org/viewvc/llvm-project?rev=334975&view=rev
Log:
[TSan] Report proper error on allocator failures instead of CHECK(0)-ing

Summary:
Following up on and complementing D44404 and other sanitizer allocators.

Currently many allocator specific errors (OOM, for example) are reported as
a text message and CHECK(0) termination, no stack, no details, not too
helpful nor informative. To improve the situation, detailed and structured
common errors were defined and reported under the appropriate conditions.

Common tests were generalized a bit to cover a slightly different TSan
stack reporting format, extended to verify errno value and returned
pointer value check is now explicit to facilitate debugging.

Reviewers: dvyukov

Subscribers: srhines, kubamracek, delcypher, #sanitizers, llvm-commits

Differential Revision: https://reviews.llvm.org/D48087

Removed:
    compiler-rt/trunk/test/tsan/allocator_returns_null.cc
Modified:
    compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_new_delete.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_stack_trace.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_stack_trace.h
    compiler-rt/trunk/lib/tsan/tests/unit/tsan_mman_test.cc
    compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/aligned_alloc-alignment.cc
    compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/pvalloc-overflow.cc
    compiler-rt/trunk/test/sanitizer_common/TestCases/Posix/posix_memalign-alignment.cc
    compiler-rt/trunk/test/sanitizer_common/TestCases/allocator_returns_null.cc

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc?rev=334975&r1=334974&r2=334975&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc Mon Jun 18 13:03:31 2018
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 #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_common.h"
 #include "sanitizer_common/sanitizer_errno.h"
 #include "sanitizer_common/sanitizer_placement_new.h"
@@ -150,13 +151,24 @@ static void SignalUnsafeCall(ThreadState
   OutputReport(thr, rep);
 }
 
+static constexpr uptr kMaxAllowedMallocSize = 1ull << 40;
+
 void *user_alloc_internal(ThreadState *thr, uptr pc, uptr sz, uptr align,
                           bool signal) {
-  if ((sz >= (1ull << 40)) || (align >= (1ull << 40)))
-    return ReturnNullOrDieOnFailure::OnBadRequest();
+  if (sz >= kMaxAllowedMallocSize || align >= kMaxAllowedMallocSize) {
+    if (AllocatorMayReturnNull())
+      return nullptr;
+    GET_STACK_TRACE_FATAL(thr, pc);
+    ReportAllocationSizeTooBig(sz, kMaxAllowedMallocSize, &stack);
+  }
   void *p = allocator()->Allocate(&thr->proc()->alloc_cache, sz, align);
-  if (UNLIKELY(p == 0))
-    return ReturnNullOrDieOnFailure::OnOOM();
+  if (UNLIKELY(!p)) {
+    SetAllocatorOutOfMemory();
+    if (AllocatorMayReturnNull())
+      return nullptr;
+    GET_STACK_TRACE_FATAL(thr, pc);
+    ReportOutOfMemory(sz, &stack);
+  }
   if (ctx && ctx->initialized)
     OnUserAlloc(thr, pc, (uptr)p, sz, true);
   if (signal)
@@ -178,8 +190,12 @@ void *user_alloc(ThreadState *thr, uptr
 }
 
 void *user_calloc(ThreadState *thr, uptr pc, uptr size, uptr n) {
-  if (UNLIKELY(CheckForCallocOverflow(size, n)))
-    return SetErrnoOnNull(ReturnNullOrDieOnFailure::OnBadRequest());
+  if (UNLIKELY(CheckForCallocOverflow(size, n))) {
+    if (AllocatorMayReturnNull())
+      return SetErrnoOnNull(nullptr);
+    GET_STACK_TRACE_FATAL(thr, pc);
+    ReportCallocOverflow(n, size, &stack);
+  }
   void *p = user_alloc_internal(thr, pc, n * size);
   if (p)
     internal_memset(p, 0, n * size);
@@ -224,7 +240,10 @@ void *user_realloc(ThreadState *thr, upt
 void *user_memalign(ThreadState *thr, uptr pc, uptr align, uptr sz) {
   if (UNLIKELY(!IsPowerOfTwo(align))) {
     errno = errno_EINVAL;
-    return ReturnNullOrDieOnFailure::OnBadRequest();
+    if (AllocatorMayReturnNull())
+      return nullptr;
+    GET_STACK_TRACE_FATAL(thr, pc);
+    ReportInvalidAllocationAlignment(align, &stack);
   }
   return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, align));
 }
@@ -232,11 +251,14 @@ void *user_memalign(ThreadState *thr, up
 int user_posix_memalign(ThreadState *thr, uptr pc, void **memptr, uptr align,
                         uptr sz) {
   if (UNLIKELY(!CheckPosixMemalignAlignment(align))) {
-    ReturnNullOrDieOnFailure::OnBadRequest();
-    return errno_EINVAL;
+    if (AllocatorMayReturnNull())
+      return errno_EINVAL;
+    GET_STACK_TRACE_FATAL(thr, pc);
+    ReportInvalidPosixMemalignAlignment(align, &stack);
   }
   void *ptr = user_alloc_internal(thr, pc, sz, align);
   if (UNLIKELY(!ptr))
+    // OOM error is already taken care of by user_alloc_internal.
     return errno_ENOMEM;
   CHECK(IsAligned((uptr)ptr, align));
   *memptr = ptr;
@@ -246,7 +268,10 @@ int user_posix_memalign(ThreadState *thr
 void *user_aligned_alloc(ThreadState *thr, uptr pc, uptr align, uptr sz) {
   if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(align, sz))) {
     errno = errno_EINVAL;
-    return ReturnNullOrDieOnFailure::OnBadRequest();
+    if (AllocatorMayReturnNull())
+      return nullptr;
+    GET_STACK_TRACE_FATAL(thr, pc);
+    ReportInvalidAlignedAllocAlignment(sz, align, &stack);
   }
   return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, align));
 }
@@ -259,7 +284,10 @@ void *user_pvalloc(ThreadState *thr, upt
   uptr PageSize = GetPageSizeCached();
   if (UNLIKELY(CheckForPvallocOverflow(sz, PageSize))) {
     errno = errno_ENOMEM;
-    return ReturnNullOrDieOnFailure::OnBadRequest();
+    if (AllocatorMayReturnNull())
+      return nullptr;
+    GET_STACK_TRACE_FATAL(thr, pc);
+    ReportPvallocOverflow(sz, &stack);
   }
   // pvalloc(0) should allocate one page.
   sz = sz ? RoundUpTo(sz, PageSize) : PageSize;

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_new_delete.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_new_delete.cc?rev=334975&r1=334974&r2=334975&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_new_delete.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_new_delete.cc Mon Jun 18 13:03:31 2018
@@ -13,8 +13,10 @@
 //===----------------------------------------------------------------------===//
 #include "interception/interception.h"
 #include "sanitizer_common/sanitizer_allocator.h"
+#include "sanitizer_common/sanitizer_allocator_report.h"
 #include "sanitizer_common/sanitizer_internal_defs.h"
 #include "tsan_interceptors.h"
+#include "tsan_rtl.h"
 
 using namespace __tsan;  // NOLINT
 
@@ -34,7 +36,10 @@ DECLARE_REAL(void, free, void *ptr)
   {  \
     SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
     p = user_alloc(thr, pc, size); \
-    if (!nothrow && UNLIKELY(!p)) DieOnFailure::OnOOM(); \
+    if (!nothrow && UNLIKELY(!p)) { \
+      GET_STACK_TRACE_FATAL(thr, pc); \
+      ReportOutOfMemory(size, &stack); \
+    } \
   }  \
   invoke_malloc_hook(p, size);  \
   return p;
@@ -46,7 +51,10 @@ DECLARE_REAL(void, free, void *ptr)
   {  \
     SCOPED_INTERCEPTOR_RAW(mangled_name, size); \
     p = user_memalign(thr, pc, (uptr)align, size); \
-    if (!nothrow && UNLIKELY(!p)) DieOnFailure::OnOOM(); \
+    if (!nothrow && UNLIKELY(!p)) { \
+      GET_STACK_TRACE_FATAL(thr, pc); \
+      ReportOutOfMemory(size, &stack); \
+    } \
   }  \
   invoke_malloc_hook(p, size);  \
   return p;

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=334975&r1=334974&r2=334975&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Mon Jun 18 13:03:31 2018
@@ -650,6 +650,10 @@ void ObtainCurrentStack(ThreadState *thr
   ExtractTagFromStack(stack, tag);
 }
 
+#define GET_STACK_TRACE_FATAL(thr, pc) \
+  VarSizeStackTrace stack; \
+  ObtainCurrentStack(thr, pc, &stack); \
+  stack.ReverseOrder();
 
 #if TSAN_COLLECT_STATS
 void StatAggregate(u64 *dst, u64 *src);

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stack_trace.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stack_trace.cc?rev=334975&r1=334974&r2=334975&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stack_trace.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stack_trace.cc Mon Jun 18 13:03:31 2018
@@ -43,4 +43,9 @@ void VarSizeStackTrace::Init(const uptr
     trace_buffer[cnt] = extra_top_pc;
 }
 
+void VarSizeStackTrace::ReverseOrder() {
+  for (u32 i = 0; i < (size >> 1); i++)
+    Swap(trace_buffer[i], trace_buffer[size - 1 - i]);
+}
+
 }  // namespace __tsan

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stack_trace.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stack_trace.h?rev=334975&r1=334974&r2=334975&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stack_trace.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stack_trace.h Mon Jun 18 13:03:31 2018
@@ -27,6 +27,10 @@ struct VarSizeStackTrace : public StackT
   ~VarSizeStackTrace();
   void Init(const uptr *pcs, uptr cnt, uptr extra_top_pc = 0);
 
+  // Reverses the current stack trace order, the top frame goes to the bottom,
+  // the last frame goes to the top.
+  void ReverseOrder();
+
  private:
   void ResizeBuffer(uptr new_size);
 

Modified: compiler-rt/trunk/lib/tsan/tests/unit/tsan_mman_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/tests/unit/tsan_mman_test.cc?rev=334975&r1=334974&r2=334975&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/tests/unit/tsan_mman_test.cc (original)
+++ compiler-rt/trunk/lib/tsan/tests/unit/tsan_mman_test.cc Mon Jun 18 13:03:31 2018
@@ -153,29 +153,12 @@ TEST(Mman, Valloc) {
   EXPECT_NE(p, (void*)0);
   EXPECT_EQ(page_size, __sanitizer_get_allocated_size(p));
   user_free(thr, 0, p);
-
-  EXPECT_DEATH(p = user_pvalloc(thr, 0, (uptr)-(page_size - 1)),
-               "allocator is terminating the process instead of returning 0");
-  EXPECT_DEATH(p = user_pvalloc(thr, 0, (uptr)-1),
-               "allocator is terminating the process instead of returning 0");
 }
 
 #if !SANITIZER_DEBUG
 // EXPECT_DEATH clones a thread with 4K stack,
 // which is overflown by tsan memory accesses functions in debug mode.
 
-TEST(Mman, CallocOverflow) {
-  ThreadState *thr = cur_thread();
-  uptr pc = 0;
-  size_t kArraySize = 4096;
-  volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max();
-  volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
-  volatile void *p = NULL;
-  EXPECT_DEATH(p = user_calloc(thr, pc, kArraySize, kArraySize2),
-               "allocator is terminating the process instead of returning 0");
-  EXPECT_EQ(0L, p);
-}
-
 TEST(Mman, Memalign) {
   ThreadState *thr = cur_thread();
 
@@ -183,12 +166,16 @@ TEST(Mman, Memalign) {
   EXPECT_NE(p, (void*)0);
   user_free(thr, 0, p);
 
+  // TODO(alekseyshl): Remove this death test when memalign is verified by
+  // tests in sanitizer_common.
   p = NULL;
   EXPECT_DEATH(p = user_memalign(thr, 0, 7, 100),
-               "allocator is terminating the process instead of returning 0");
+               "invalid-allocation-alignment");
   EXPECT_EQ(0L, p);
 }
 
+#endif
+
 TEST(Mman, PosixMemalign) {
   ThreadState *thr = cur_thread();
 
@@ -197,16 +184,6 @@ TEST(Mman, PosixMemalign) {
   EXPECT_NE(p, (void*)0);
   EXPECT_EQ(res, 0);
   user_free(thr, 0, p);
-
-  p = NULL;
-  // Alignment is not a power of two, although is a multiple of sizeof(void*).
-  EXPECT_DEATH(res = user_posix_memalign(thr, 0, &p, 3 * sizeof(p), 100),
-               "allocator is terminating the process instead of returning 0");
-  EXPECT_EQ(0L, p);
-  // Alignment is not a multiple of sizeof(void*), although is a power of 2.
-  EXPECT_DEATH(res = user_posix_memalign(thr, 0, &p, 2, 100),
-               "allocator is terminating the process instead of returning 0");
-  EXPECT_EQ(0L, p);
 }
 
 TEST(Mman, AlignedAlloc) {
@@ -215,18 +192,6 @@ TEST(Mman, AlignedAlloc) {
   void *p = user_aligned_alloc(thr, 0, 8, 64);
   EXPECT_NE(p, (void*)0);
   user_free(thr, 0, p);
-
-  p = NULL;
-  // Alignement is not a power of 2.
-  EXPECT_DEATH(p = user_aligned_alloc(thr, 0, 7, 100),
-               "allocator is terminating the process instead of returning 0");
-  EXPECT_EQ(0L, p);
-  // Size is not a multiple of alignment.
-  EXPECT_DEATH(p = user_aligned_alloc(thr, 0, 8, 100),
-               "allocator is terminating the process instead of returning 0");
-  EXPECT_EQ(0L, p);
 }
 
-#endif
-
 }  // namespace __tsan

Modified: compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/aligned_alloc-alignment.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/aligned_alloc-alignment.cc?rev=334975&r1=334974&r2=334975&view=diff
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/aligned_alloc-alignment.cc (original)
+++ compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/aligned_alloc-alignment.cc Mon Jun 18 13:03:31 2018
@@ -1,14 +1,23 @@
 // RUN: %clangxx %collect_stack_traces -O0 %s -o %t
+
+// Alignment is not a power of 2:
 // RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 17 2>&1 | FileCheck %s
+// Size is not a multiple of alignment:
+// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 8 2>&1 | FileCheck %s
+// Alignment is 0:
 // RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 0 2>&1 | FileCheck %s
+
+// The same for allocator_may_return_null=1:
 // RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 17 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
+// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 8 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
 // RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
 
 // REQUIRES: stable-runtime
 
-// UNSUPPORTED: android, tsan, ubsan
+// UNSUPPORTED: android, ubsan
 
 #include <assert.h>
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -21,12 +30,14 @@ int main(int argc, char **argv) {
   void *p = aligned_alloc(alignment, 100);
   // CHECK: {{ERROR: .*Sanitizer: invalid alignment requested in aligned_alloc}}
   // Handle a case when aligned_alloc is aliased by memalign.
-  // CHECK: {{#0 0x.* in .*}}{{aligned_alloc|memalign}}
-  // CHECK: {{#1 0x.* in main .*aligned_alloc-alignment.cc:}}[[@LINE-4]]
+  // CHECK: {{#0 .*}}{{aligned_alloc|memalign}}
+  // CHECK: {{#1 .*main .*aligned_alloc-alignment.cc:}}[[@LINE-4]]
   // CHECK: {{SUMMARY: .*Sanitizer: invalid-aligned-alloc-alignment}}
 
-  printf("pointer after failed aligned_alloc: %zd\n", (size_t)p);
-  // CHECK-NULL: pointer after failed aligned_alloc: 0
+  // The NULL pointer is printed differently on different systems, while (long)0
+  // is always the same.
+  fprintf(stderr, "errno: %d, p: %lx\n", errno, (long)p);
+  // CHECK-NULL: errno: 22, p: 0
 
   return 0;
 }

Modified: compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/pvalloc-overflow.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/pvalloc-overflow.cc?rev=334975&r1=334974&r2=334975&view=diff
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/pvalloc-overflow.cc (original)
+++ compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/pvalloc-overflow.cc Mon Jun 18 13:03:31 2018
@@ -6,7 +6,7 @@
 
 // REQUIRES: stable-runtime
 
-// UNSUPPORTED: android, freebsd, netbsd, tsan, ubsan
+// UNSUPPORTED: android, freebsd, netbsd, ubsan
 
 // Checks that pvalloc overflows are caught. If the allocator is allowed to
 // return null, the errno should be set to ENOMEM.
@@ -14,6 +14,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <malloc.h>
+#include <stdio.h>
 #include <stdint.h>
 #include <string.h>
 #include <unistd.h>
@@ -32,15 +33,15 @@ int main(int argc, char *argv[]) {
   } else {
     assert(0);
   }
+  // CHECK: {{ERROR: .*Sanitizer: pvalloc parameters overflow: size .* rounded up to system page size .* cannot be represented in type size_t}}
+  // CHECK: {{#0 .*pvalloc}}
+  // CHECK: {{#1 .*main .*pvalloc-overflow.cc:}}
+  // CHECK: {{SUMMARY: .*Sanitizer: pvalloc-overflow}}
+
+  // The NULL pointer is printed differently on different systems, while (long)0
+  // is always the same.
+  fprintf(stderr, "errno: %d, p: %lx\n", errno, (long)p);
+  // CHECK-NULL: errno: 12, p: 0
 
-  fprintf(stderr, "errno: %d\n", errno);
-
-  return p != nullptr;
+  return 0;
 }
-
-// CHECK: {{ERROR: .*Sanitizer: pvalloc parameters overflow: size .* rounded up to system page size .* cannot be represented in type size_t}}
-// CHECK: {{#0 0x.* in .*pvalloc}}
-// CHECK: {{#1 0x.* in main .*pvalloc-overflow.cc:}}
-// CHECK: {{SUMMARY: .*Sanitizer: pvalloc-overflow}}
-
-// CHECK-NULL: errno: 12

Modified: compiler-rt/trunk/test/sanitizer_common/TestCases/Posix/posix_memalign-alignment.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/TestCases/Posix/posix_memalign-alignment.cc?rev=334975&r1=334974&r2=334975&view=diff
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/TestCases/Posix/posix_memalign-alignment.cc (original)
+++ compiler-rt/trunk/test/sanitizer_common/TestCases/Posix/posix_memalign-alignment.cc Mon Jun 18 13:03:31 2018
@@ -1,14 +1,26 @@
 // RUN: %clangxx %collect_stack_traces -O0 %s -o %t
+
+// Alignment is not a power of two:
 // RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 17 2>&1 | FileCheck %s
+// Alignment is not a power of two, although is a multiple of sizeof(void*):
+// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 24 2>&1 | FileCheck %s
+// Alignment is not a multiple of sizeof(void*), although is a power of 2:
+// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 2 2>&1 | FileCheck %s
+// Alignment is 0:
 // RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 0 2>&1 | FileCheck %s
+
+// The same for allocator_may_return_null=1:
 // RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 17 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
+// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 24 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
+// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
 // RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
 
 // REQUIRES: stable-runtime
 
-// UNSUPPORTED: tsan, ubsan
+// UNSUPPORTED: ubsan
 
 #include <assert.h>
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -16,16 +28,20 @@ int main(int argc, char **argv) {
   assert(argc == 2);
   const int alignment = atoi(argv[1]);
 
-  void *p = reinterpret_cast<void*>(42);
+  void* const kInitialPtrValue = reinterpret_cast<void*>(0x2a);
+  void *p = kInitialPtrValue;
 
+  errno = 0;
   int res = posix_memalign(&p, alignment, 100);
   // CHECK: {{ERROR: .*Sanitizer: invalid alignment requested in posix_memalign}}
-  // CHECK: {{#0 0x.* in .*posix_memalign}}
-  // CHECK: {{#1 0x.* in main .*posix_memalign-alignment.cc:}}[[@LINE-3]]
+  // CHECK: {{#0 .*posix_memalign}}
+  // CHECK: {{#1 .*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
+  // The NULL pointer is printed differently on different systems, while (long)0
+  // is always the same.
+  fprintf(stderr, "errno: %d, res: %d, p: %lx\n", errno, res, (long)p);
+  // CHECK-NULL: errno: 0, res: 22, p: 2a
 
   return 0;
 }

Modified: compiler-rt/trunk/test/sanitizer_common/TestCases/allocator_returns_null.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/TestCases/allocator_returns_null.cc?rev=334975&r1=334974&r2=334975&view=diff
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/TestCases/allocator_returns_null.cc (original)
+++ compiler-rt/trunk/test/sanitizer_common/TestCases/allocator_returns_null.cc Mon Jun 18 13:03:31 2018
@@ -1,8 +1,8 @@
 // Test the behavior of malloc/calloc/realloc/new when the allocation size
 // exceeds the sanitizer's allocator max allowed one.
 // By default (allocator_may_return_null=0) the process should crash. With
-// allocator_may_return_null=1 the allocator should return 0 and set errno to
-// the appropriate error code.
+// allocator_may_return_null=1 the allocator should return nullptr and set errno
+// to the appropriate error code.
 //
 // RUN: %clangxx -O0 %s -o %t
 // RUN: not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH
@@ -36,7 +36,7 @@
 // RUN:   | FileCheck %s --check-prefix=CHECK-NULL
 
 // TODO(alekseyshl): win32 is disabled due to failing errno tests, fix it there.
-// UNSUPPORTED: tsan, ubsan, win32
+// UNSUPPORTED: ubsan, win32
 
 #include <assert.h>
 #include <errno.h>
@@ -51,12 +51,8 @@ int main(int argc, char **argv) {
   const char *action = argv[1];
   fprintf(stderr, "%s:\n", action);
 
-  // The maximum value of all supported sanitizers:
-  // ASan: asan_allocator.cc, search for kMaxAllowedMallocSize.
-  // LSan: lsan_allocator.cc, search for kMaxAllowedMallocSize.
-  // ASan + LSan: ASan limit is used.
-  // MSan: msan_allocator.cc, search for kMaxAllowedMallocSize.
-  // TSan: tsan_mman.cc, user_alloc_internal function.
+  // The maximum value of all supported sanitizers (search for
+  // kMaxAllowedMallocSize). For ASan + LSan, ASan limit is used.
   static const size_t kMaxAllowedMallocSizePlusOne =
 #if __LP64__ || defined(_WIN64)
       (1ULL << 40) + 1;
@@ -90,11 +86,11 @@ int main(int argc, char **argv) {
     assert(0);
   }
 
-  fprintf(stderr, "errno: %d\n", errno);
+  // The NULL pointer is printed differently on different systems, while (long)0
+  // is always the same.
+  fprintf(stderr, "errno: %d, x: %lx\n", errno, (long)x);
 
-  free(x);
-
-  return x != nullptr;
+  return 0;
 }
 
 // CHECK-mCRASH: malloc:
@@ -115,4 +111,4 @@ int main(int argc, char **argv) {
 // CHECK-nnCRASH: {{SUMMARY: .*Sanitizer: allocation-size-too-big}}
 
 // CHECK-NULL: {{malloc|calloc|calloc-overflow|realloc|realloc-after-malloc|new-nothrow}}
-// CHECK-NULL: errno: 12
+// CHECK-NULL: errno: 12, x: 0

Removed: compiler-rt/trunk/test/tsan/allocator_returns_null.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/allocator_returns_null.cc?rev=334974&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/allocator_returns_null.cc (original)
+++ compiler-rt/trunk/test/tsan/allocator_returns_null.cc (removed)
@@ -1,124 +0,0 @@
-// Test the behavior of malloc/calloc/realloc/new when the allocation size is
-// more than TSan allocator's max allowed one.
-// By default (allocator_may_return_null=0) the process should crash.
-// With allocator_may_return_null=1 the allocator should return 0, except the
-// operator new(), which should crash anyway (operator new(std::nothrow) should
-// return nullptr, indeed).
-//
-// RUN: %clangxx_tsan -O0 %s -o %t
-// RUN: not %run %t malloc 2>&1 | FileCheck %s --check-prefix=CHECK-mCRASH
-// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t malloc 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-mCRASH
-// RUN: %env_tsan_opts=allocator_may_return_null=1     %run %t malloc 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-mNULL
-// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t calloc 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-cCRASH
-// RUN: %env_tsan_opts=allocator_may_return_null=1     %run %t calloc 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-cNULL
-// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t calloc-overflow 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-coCRASH
-// RUN: %env_tsan_opts=allocator_may_return_null=1     %run %t calloc-overflow 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-coNULL
-// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t realloc 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-rCRASH
-// RUN: %env_tsan_opts=allocator_may_return_null=1     %run %t realloc 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-rNULL
-// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t realloc-after-malloc 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-mrCRASH
-// RUN: %env_tsan_opts=allocator_may_return_null=1     %run %t realloc-after-malloc 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-mrNULL
-// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t new 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-nCRASH
-// RUN: %env_tsan_opts=allocator_may_return_null=1 not %run %t new 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-nCRASH
-// RUN: %env_tsan_opts=allocator_may_return_null=0 not %run %t new-nothrow 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-nnCRASH
-// RUN: %env_tsan_opts=allocator_may_return_null=1     %run %t new-nothrow 2>&1 \
-// RUN:   | FileCheck %s --check-prefix=CHECK-nnNULL
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits>
-#include <new>
-
-int main(int argc, char **argv) {
-  // Disable stderr buffering. Needed on Windows.
-  setvbuf(stderr, NULL, _IONBF, 0);
-
-  assert(argc == 2);
-  const char *action = argv[1];
-  fprintf(stderr, "%s:\n", action);
-
-  // The limit enforced in tsan_mman.cc, user_alloc_internal function.
-  static const size_t kMaxAllowedMallocSizePlusOne = (1ULL << 40) + 1;
-
-  void *x = 0;
-  if (!strcmp(action, "malloc")) {
-    x = malloc(kMaxAllowedMallocSizePlusOne);
-  } else if (!strcmp(action, "calloc")) {
-    x = calloc((kMaxAllowedMallocSizePlusOne / 4) + 1, 4);
-  } else if (!strcmp(action, "calloc-overflow")) {
-    volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max();
-    size_t kArraySize = 4096;
-    volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
-    x = calloc(kArraySize, kArraySize2);
-  } else if (!strcmp(action, "realloc")) {
-    x = realloc(0, kMaxAllowedMallocSizePlusOne);
-  } else if (!strcmp(action, "realloc-after-malloc")) {
-    char *t = (char*)malloc(100);
-    *t = 42;
-    x = realloc(t, kMaxAllowedMallocSizePlusOne);
-    assert(*t == 42);
-  } else if (!strcmp(action, "new")) {
-    x = operator new(kMaxAllowedMallocSizePlusOne);
-  } else if (!strcmp(action, "new-nothrow")) {
-    x = operator new(kMaxAllowedMallocSizePlusOne, std::nothrow);
-  } else {
-    assert(0);
-  }
-
-  fprintf(stderr, "errno: %d\n", errno);
-
-  // The NULL pointer is printed differently on different systems, while (long)0
-  // is always the same.
-  fprintf(stderr, "x: %lx\n", (long)x);
-  free(x);
-
-  return x != 0;
-}
-
-// CHECK-mCRASH: malloc:
-// CHECK-mCRASH: ThreadSanitizer's allocator is terminating the process
-// CHECK-cCRASH: calloc:
-// CHECK-cCRASH: ThreadSanitizer's allocator is terminating the process
-// CHECK-coCRASH: calloc-overflow:
-// CHECK-coCRASH: ThreadSanitizer's allocator is terminating the process
-// CHECK-rCRASH: realloc:
-// CHECK-rCRASH: ThreadSanitizer's allocator is terminating the process
-// CHECK-mrCRASH: realloc-after-malloc:
-// CHECK-mrCRASH: ThreadSanitizer's allocator is terminating the process
-// CHECK-nCRASH: new:
-// CHECK-nCRASH: ThreadSanitizer's allocator is terminating the process
-// CHECK-nnCRASH: new-nothrow:
-// CHECK-nnCRASH: ThreadSanitizer's allocator is terminating the process
-
-// CHECK-mNULL: malloc:
-// CHECK-mNULL: errno: 12
-// CHECK-mNULL: x: 0
-// CHECK-cNULL: calloc:
-// CHECK-cNULL: errno: 12
-// CHECK-cNULL: x: 0
-// CHECK-coNULL: calloc-overflow:
-// CHECK-coNULL: errno: 12
-// CHECK-coNULL: x: 0
-// CHECK-rNULL: realloc:
-// CHECK-rNULL: errno: 12
-// CHECK-rNULL: x: 0
-// CHECK-mrNULL: realloc-after-malloc:
-// CHECK-mrNULL: errno: 12
-// CHECK-mrNULL: x: 0
-// CHECK-nnNULL: new-nothrow:
-// CHECK-nnNULL: x: 0




More information about the llvm-commits mailing list