[compiler-rt] r359708 - [sanitizer] Implement reallocarray.

Evgeniy Stepanov via llvm-commits llvm-commits at lists.llvm.org
Wed May 1 10:33:02 PDT 2019


Author: eugenis
Date: Wed May  1 10:33:01 2019
New Revision: 359708

URL: http://llvm.org/viewvc/llvm-project?rev=359708&view=rev
Log:
[sanitizer] Implement reallocarray.

Summary:
It's a cross of calloc and realloc. Sanitizers implement calloc-like check for size
overflow.

Reviewers: vitalybuka, kcc

Subscribers: kubamracek, #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

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

Added:
    compiler-rt/trunk/test/sanitizer_common/TestCases/reallocarray-overflow.cc
Modified:
    compiler-rt/trunk/include/sanitizer/hwasan_interface.h
    compiler-rt/trunk/lib/asan/asan_allocator.cc
    compiler-rt/trunk/lib/asan/asan_allocator.h
    compiler-rt/trunk/lib/asan/asan_errors.cc
    compiler-rt/trunk/lib/asan/asan_errors.h
    compiler-rt/trunk/lib/asan/asan_malloc_linux.cc
    compiler-rt/trunk/lib/asan/asan_report.cc
    compiler-rt/trunk/lib/asan/asan_report.h
    compiler-rt/trunk/lib/hwasan/hwasan.h
    compiler-rt/trunk/lib/hwasan/hwasan_allocator.cpp
    compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cpp
    compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h
    compiler-rt/trunk/lib/lsan/lsan_allocator.cc
    compiler-rt/trunk/lib/lsan/lsan_allocator.h
    compiler-rt/trunk/lib/lsan/lsan_interceptors.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/sanitizer_common/sanitizer_allocator.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_report.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_report.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h
    compiler-rt/trunk/test/hwasan/TestCases/realloc-test.cc
    compiler-rt/trunk/test/hwasan/TestCases/sanitizer_malloc.cc
    compiler-rt/trunk/test/hwasan/TestCases/sizes.cpp

Modified: compiler-rt/trunk/include/sanitizer/hwasan_interface.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/sanitizer/hwasan_interface.h?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/include/sanitizer/hwasan_interface.h (original)
+++ compiler-rt/trunk/include/sanitizer/hwasan_interface.h Wed May  1 10:33:01 2019
@@ -87,6 +87,7 @@ extern "C" {
   void __sanitizer_malloc_stats(void);
   void * __sanitizer_calloc(size_t nmemb, size_t size);
   void * __sanitizer_realloc(void *ptr, size_t size);
+  void * __sanitizer_reallocarray(void *ptr, size_t nmemb, size_t size);
   void * __sanitizer_malloc(size_t size);
 #ifdef __cplusplus
 }  // extern "C"

Modified: compiler-rt/trunk/lib/asan/asan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator.cc?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator.cc Wed May  1 10:33:01 2019
@@ -879,6 +879,17 @@ void *asan_calloc(uptr nmemb, uptr size,
   return SetErrnoOnNull(instance.Calloc(nmemb, size, stack));
 }
 
+void *asan_reallocarray(void *p, uptr nmemb, uptr size,
+                        BufferedStackTrace *stack) {
+  if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+    errno = errno_ENOMEM;
+    if (AllocatorMayReturnNull())
+      return nullptr;
+    ReportReallocArrayOverflow(nmemb, size, stack);
+  }
+  return asan_realloc(p, nmemb * size, stack);
+}
+
 void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack) {
   if (!p)
     return SetErrnoOnNull(instance.Allocate(size, 8, stack, FROM_MALLOC, true));

Modified: compiler-rt/trunk/lib/asan/asan_allocator.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_allocator.h?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_allocator.h (original)
+++ compiler-rt/trunk/lib/asan/asan_allocator.h Wed May  1 10:33:01 2019
@@ -219,6 +219,8 @@ void asan_delete(void *ptr, uptr size, u
 void *asan_malloc(uptr size, BufferedStackTrace *stack);
 void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack);
 void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack);
+void *asan_reallocarray(void *p, uptr nmemb, uptr size,
+                        BufferedStackTrace *stack);
 void *asan_valloc(uptr size, BufferedStackTrace *stack);
 void *asan_pvalloc(uptr size, BufferedStackTrace *stack);
 

Modified: compiler-rt/trunk/lib/asan/asan_errors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_errors.cc?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_errors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_errors.cc Wed May  1 10:33:01 2019
@@ -177,6 +177,19 @@ void ErrorCallocOverflow::Print() {
   ReportErrorSummary(scariness.GetDescription(), stack);
 }
 
+void ErrorReallocArrayOverflow::Print() {
+  Decorator d;
+  Printf("%s", d.Error());
+  Report(
+      "ERROR: AddressSanitizer: reallocarray parameters overflow: count * size "
+      "(%zd * %zd) cannot be represented in type size_t (thread %s)\n",
+      count, size, AsanThreadIdAndName(tid).c_str());
+  Printf("%s", d.Default());
+  stack->Print();
+  PrintHintAllocatorCannotReturnNull();
+  ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
 void ErrorPvallocOverflow::Print() {
   Decorator d;
   Printf("%s", d.Error());

Modified: compiler-rt/trunk/lib/asan/asan_errors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_errors.h?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_errors.h (original)
+++ compiler-rt/trunk/lib/asan/asan_errors.h Wed May  1 10:33:01 2019
@@ -163,6 +163,21 @@ struct ErrorCallocOverflow : ErrorBase {
   void Print();
 };
 
+struct ErrorReallocArrayOverflow : ErrorBase {
+  const BufferedStackTrace *stack;
+  uptr count;
+  uptr size;
+
+  ErrorReallocArrayOverflow() = default;  // (*)
+  ErrorReallocArrayOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_,
+                            uptr size_)
+      : ErrorBase(tid, 10, "reallocarray-overflow"),
+        stack(stack_),
+        count(count_),
+        size(size_) {}
+  void Print();
+};
+
 struct ErrorPvallocOverflow : ErrorBase {
   const BufferedStackTrace *stack;
   uptr size;
@@ -371,6 +386,7 @@ struct ErrorGeneric : ErrorBase {
   macro(MallocUsableSizeNotOwned)               \
   macro(SanitizerGetAllocatedSizeNotOwned)      \
   macro(CallocOverflow)                         \
+  macro(ReallocArrayOverflow)                   \
   macro(PvallocOverflow)                        \
   macro(InvalidAllocationAlignment)             \
   macro(InvalidAlignedAllocAlignment)           \

Modified: compiler-rt/trunk/lib/asan/asan_malloc_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_malloc_linux.cc?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_linux.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_linux.cc Wed May  1 10:33:01 2019
@@ -165,6 +165,14 @@ INTERCEPTOR(void*, realloc, void *ptr, u
   return asan_realloc(ptr, size, &stack);
 }
 
+#if SANITIZER_INTERCEPT_REALLOCARRAY
+INTERCEPTOR(void*, reallocarray, void *ptr, uptr nmemb, uptr size) {
+  ENSURE_ASAN_INITED();
+  GET_STACK_TRACE_MALLOC;
+  return asan_reallocarray(ptr, nmemb, size, &stack);
+}
+#endif  // SANITIZER_INTERCEPT_REALLOCARRAY
+
 #if SANITIZER_INTERCEPT_MEMALIGN
 INTERCEPTOR(void*, memalign, uptr boundary, uptr size) {
   GET_STACK_TRACE_MALLOC;

Modified: compiler-rt/trunk/lib/asan/asan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.cc?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_report.cc Wed May  1 10:33:01 2019
@@ -263,6 +263,13 @@ void ReportCallocOverflow(uptr count, up
   in_report.ReportError(error);
 }
 
+void ReportReallocArrayOverflow(uptr count, uptr size,
+                                BufferedStackTrace *stack) {
+  ScopedInErrorReport in_report(/*fatal*/ true);
+  ErrorReallocArrayOverflow error(GetCurrentTidOrInvalid(), stack, count, size);
+  in_report.ReportError(error);
+}
+
 void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack) {
   ScopedInErrorReport in_report(/*fatal*/ true);
   ErrorPvallocOverflow error(GetCurrentTidOrInvalid(), stack, size);

Modified: compiler-rt/trunk/lib/asan/asan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_report.h?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_report.h (original)
+++ compiler-rt/trunk/lib/asan/asan_report.h Wed May  1 10:33:01 2019
@@ -61,6 +61,8 @@ void ReportMallocUsableSizeNotOwned(uptr
 void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr,
                                              BufferedStackTrace *stack);
 void ReportCallocOverflow(uptr count, uptr size, BufferedStackTrace *stack);
+void ReportReallocArrayOverflow(uptr count, uptr size,
+                                BufferedStackTrace *stack);
 void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack);
 void ReportInvalidAllocationAlignment(uptr alignment,
                                       BufferedStackTrace *stack);

Modified: compiler-rt/trunk/lib/hwasan/hwasan.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan.h?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan.h Wed May  1 10:33:01 2019
@@ -81,6 +81,7 @@ void HwasanAllocatorThreadFinish();
 void *hwasan_malloc(uptr size, StackTrace *stack);
 void *hwasan_calloc(uptr nmemb, uptr size, StackTrace *stack);
 void *hwasan_realloc(void *ptr, uptr size, StackTrace *stack);
+void *hwasan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack);
 void *hwasan_valloc(uptr size, StackTrace *stack);
 void *hwasan_pvalloc(uptr size, StackTrace *stack);
 void *hwasan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack);

Modified: compiler-rt/trunk/lib/hwasan/hwasan_allocator.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_allocator.cpp?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_allocator.cpp (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_allocator.cpp Wed May  1 10:33:01 2019
@@ -341,6 +341,16 @@ void *hwasan_realloc(void *ptr, uptr siz
   return SetErrnoOnNull(HwasanReallocate(stack, ptr, size, sizeof(u64)));
 }
 
+void *hwasan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack) {
+  if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+    errno = errno_ENOMEM;
+    if (AllocatorMayReturnNull())
+      return nullptr;
+    ReportReallocArrayOverflow(nmemb, size, stack);
+  }
+  return hwasan_realloc(ptr, nmemb * size, stack);
+}
+
 void *hwasan_valloc(uptr size, StackTrace *stack) {
   return SetErrnoOnNull(
       HwasanAllocate(stack, size, GetPageSizeCached(), false));

Modified: compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cpp?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cpp (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cpp Wed May  1 10:33:01 2019
@@ -178,6 +178,11 @@ void * __sanitizer_realloc(void *ptr, up
   return hwasan_realloc(ptr, size, &stack);
 }
 
+void * __sanitizer_reallocarray(void *ptr, uptr nmemb, uptr size) {
+  GET_MALLOC_STACK_TRACE;
+  return hwasan_reallocarray(ptr, nmemb, size, &stack);
+}
+
 void * __sanitizer_malloc(uptr size) {
   GET_MALLOC_STACK_TRACE;
   if (UNLIKELY(!hwasan_init_is_running))
@@ -204,6 +209,7 @@ INTERCEPTOR_ALIAS(void, free, void *ptr)
 INTERCEPTOR_ALIAS(uptr, malloc_usable_size, const void *ptr);
 INTERCEPTOR_ALIAS(void *, calloc, SIZE_T nmemb, SIZE_T size);
 INTERCEPTOR_ALIAS(void *, realloc, void *ptr, SIZE_T size);
+INTERCEPTOR_ALIAS(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size);
 INTERCEPTOR_ALIAS(void *, malloc, SIZE_T size);
 
 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD

Modified: compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h Wed May  1 10:33:01 2019
@@ -198,6 +198,9 @@ SANITIZER_INTERFACE_ATTRIBUTE
 void * __sanitizer_realloc(void *ptr, uptr size);
 
 SANITIZER_INTERFACE_ATTRIBUTE
+void * __sanitizer_reallocarray(void *ptr, uptr nmemb, uptr size);
+
+SANITIZER_INTERFACE_ATTRIBUTE
 void * __sanitizer_malloc(uptr size);
 
 SANITIZER_INTERFACE_ATTRIBUTE

Modified: compiler-rt/trunk/lib/lsan/lsan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_allocator.cc?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_allocator.cc (original)
+++ compiler-rt/trunk/lib/lsan/lsan_allocator.cc Wed May  1 10:33:01 2019
@@ -185,6 +185,17 @@ void *lsan_realloc(void *p, uptr size, c
   return SetErrnoOnNull(Reallocate(stack, p, size, 1));
 }
 
+void *lsan_reallocarray(void *ptr, uptr nmemb, uptr size,
+                        const StackTrace &stack) {
+  if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+    errno = errno_ENOMEM;
+    if (AllocatorMayReturnNull())
+      return nullptr;
+    ReportReallocArrayOverflow(nmemb, size, &stack);
+  }
+  return lsan_realloc(ptr, nmemb * size, stack);
+}
+
 void *lsan_calloc(uptr nmemb, uptr size, const StackTrace &stack) {
   return SetErrnoOnNull(Calloc(nmemb, size, stack));
 }

Modified: compiler-rt/trunk/lib/lsan/lsan_allocator.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_allocator.h?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_allocator.h (original)
+++ compiler-rt/trunk/lib/lsan/lsan_allocator.h Wed May  1 10:33:01 2019
@@ -116,6 +116,8 @@ void *lsan_memalign(uptr alignment, uptr
 void *lsan_malloc(uptr size, const StackTrace &stack);
 void lsan_free(void *p);
 void *lsan_realloc(void *p, uptr size, const StackTrace &stack);
+void *lsan_reallocarray(void *p, uptr nmemb, uptr size,
+                        const StackTrace &stack);
 void *lsan_calloc(uptr nmemb, uptr size, const StackTrace &stack);
 void *lsan_valloc(uptr size, const StackTrace &stack);
 void *lsan_pvalloc(uptr size, const StackTrace &stack);

Modified: compiler-rt/trunk/lib/lsan/lsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_interceptors.cc?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/lsan/lsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/lsan/lsan_interceptors.cc Wed May  1 10:33:01 2019
@@ -83,6 +83,12 @@ INTERCEPTOR(void*, realloc, void *q, upt
   return lsan_realloc(q, size, stack);
 }
 
+INTERCEPTOR(void*, reallocarray, void *q, uptr nmemb, uptr size) {
+  ENSURE_LSAN_INITED;
+  GET_STACK_TRACE_MALLOC;
+  return lsan_reallocarray(q, nmemb, size, stack);
+}
+
 INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
   ENSURE_LSAN_INITED;
   GET_STACK_TRACE_MALLOC;

Modified: compiler-rt/trunk/lib/msan/msan.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.h?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan.h (original)
+++ compiler-rt/trunk/lib/msan/msan.h Wed May  1 10:33:01 2019
@@ -288,6 +288,7 @@ void MsanDeallocate(StackTrace *stack, v
 void *msan_malloc(uptr size, StackTrace *stack);
 void *msan_calloc(uptr nmemb, uptr size, StackTrace *stack);
 void *msan_realloc(void *ptr, uptr size, StackTrace *stack);
+void *msan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack);
 void *msan_valloc(uptr size, StackTrace *stack);
 void *msan_pvalloc(uptr size, StackTrace *stack);
 void *msan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack);

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=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_allocator.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_allocator.cc Wed May  1 10:33:01 2019
@@ -261,6 +261,16 @@ void *msan_realloc(void *ptr, uptr size,
   return SetErrnoOnNull(MsanReallocate(stack, ptr, size, sizeof(u64)));
 }
 
+void *msan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack) {
+  if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
+    errno = errno_ENOMEM;
+    if (AllocatorMayReturnNull())
+      return nullptr;
+    ReportReallocArrayOverflow(nmemb, size, stack);
+  }
+  return msan_realloc(ptr, nmemb * size, stack);
+}
+
 void *msan_valloc(uptr size, StackTrace *stack) {
   return SetErrnoOnNull(MsanAllocate(stack, size, GetPageSizeCached(), false));
 }

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=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_interceptors.cc Wed May  1 10:33:01 2019
@@ -907,6 +907,11 @@ INTERCEPTOR(void *, realloc, void *ptr,
   return msan_realloc(ptr, size, &stack);
 }
 
+INTERCEPTOR(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size) {
+  GET_MALLOC_STACK_TRACE;
+  return msan_reallocarray(ptr, nmemb, size, &stack);
+}
+
 INTERCEPTOR(void *, malloc, SIZE_T size) {
   GET_MALLOC_STACK_TRACE;
   if (UNLIKELY(!msan_inited))
@@ -1597,6 +1602,7 @@ void InitializeInterceptors() {
   INTERCEPT_FUNCTION(malloc);
   INTERCEPT_FUNCTION(calloc);
   INTERCEPT_FUNCTION(realloc);
+  INTERCEPT_FUNCTION(reallocarray);
   INTERCEPT_FUNCTION(free);
   MSAN_MAYBE_INTERCEPT_CFREE;
   MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE;

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.cc?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator.cc Wed May  1 10:33:01 2019
@@ -170,6 +170,18 @@ void *InternalRealloc(void *addr, uptr s
   return (char*)p + sizeof(u64);
 }
 
+void *InternalReallocArray(void *addr, uptr count, uptr size,
+                           InternalAllocatorCache *cache) {
+  if (UNLIKELY(CheckForCallocOverflow(count, size))) {
+    Report(
+        "FATAL: %s: reallocarray parameters overflow: count * size (%zd * %zd) "
+        "cannot be represented in type size_t\n",
+        SanitizerToolName, count, size);
+    Die();
+  }
+  return InternalRealloc(addr, count * size, cache);
+}
+
 void *InternalCalloc(uptr count, uptr size, InternalAllocatorCache *cache) {
   if (UNLIKELY(CheckForCallocOverflow(count, size))) {
     Report("FATAL: %s: calloc parameters overflow: count * size (%zd * %zd) "

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_internal.h Wed May  1 10:33:01 2019
@@ -48,7 +48,9 @@ void *InternalAlloc(uptr size, InternalA
                     uptr alignment = 0);
 void *InternalRealloc(void *p, uptr size,
                       InternalAllocatorCache *cache = nullptr);
-void *InternalCalloc(uptr countr, uptr size,
+void *InternalReallocArray(void *p, uptr count, uptr size,
+                           InternalAllocatorCache *cache = nullptr);
+void *InternalCalloc(uptr count, uptr size,
                      InternalAllocatorCache *cache = nullptr);
 void InternalFree(void *p, InternalAllocatorCache *cache = nullptr);
 InternalAllocator *internal_allocator();

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_report.cc?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_report.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_report.cc Wed May  1 10:33:01 2019
@@ -51,6 +51,18 @@ void NORETURN ReportCallocOverflow(uptr
   Die();
 }
 
+void NORETURN ReportReallocArrayOverflow(uptr count, uptr size,
+                                         const StackTrace *stack) {
+  {
+    ScopedAllocatorErrorReport report("reallocarray-overflow", stack);
+    Report(
+        "ERROR: %s: reallocarray 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);

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_report.h?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_report.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_allocator_report.h Wed May  1 10:33:01 2019
@@ -21,6 +21,8 @@ namespace __sanitizer {
 
 void NORETURN ReportCallocOverflow(uptr count, uptr size,
                                    const StackTrace *stack);
+void NORETURN ReportReallocArrayOverflow(uptr count, uptr size,
+                                         const StackTrace *stack);
 void NORETURN ReportPvallocOverflow(uptr size, const StackTrace *stack);
 void NORETURN ReportInvalidAllocationAlignment(uptr alignment,
                                                const StackTrace *stack);

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h Wed May  1 10:33:01 2019
@@ -487,6 +487,7 @@
 #define SANITIZER_INTERCEPT_CFREE \
   (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_OPENBSD && SI_NOT_FUCHSIA && \
   SI_NOT_RTEMS)
+#define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX
 #define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC && SI_NOT_RTEMS)
 #define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_OPENBSD)
 #define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Wed May  1 10:33:01 2019
@@ -706,6 +706,19 @@ TSAN_INTERCEPTOR(void*, realloc, void *p
   return p;
 }
 
+TSAN_INTERCEPTOR(void*, reallocarray, void *p, uptr size, uptr n) {
+  if (in_symbolizer())
+    return InternalReallocArray(p, size, n);
+  if (p)
+    invoke_free_hook(p);
+  {
+    SCOPED_INTERCEPTOR_RAW(reallocarray, p, size, n);
+    p = user_reallocarray(thr, pc, p, size, n);
+  }
+  invoke_malloc_hook(p, size);
+  return p;
+}
+
 TSAN_INTERCEPTOR(void, free, void *p) {
   if (p == 0)
     return;
@@ -2667,6 +2680,7 @@ void InitializeInterceptors() {
   TSAN_INTERCEPT(__libc_memalign);
   TSAN_INTERCEPT(calloc);
   TSAN_INTERCEPT(realloc);
+  TSAN_INTERCEPT(reallocarray);
   TSAN_INTERCEPT(free);
   TSAN_INTERCEPT(cfree);
   TSAN_INTERCEPT(munmap);

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=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_mman.cc Wed May  1 10:33:01 2019
@@ -201,6 +201,16 @@ void *user_calloc(ThreadState *thr, uptr
   return SetErrnoOnNull(p);
 }
 
+void *user_reallocarray(ThreadState *thr, uptr pc, void *p, uptr size, uptr n) {
+  if (UNLIKELY(CheckForCallocOverflow(size, n))) {
+    if (AllocatorMayReturnNull())
+      return SetErrnoOnNull(nullptr);
+    GET_STACK_TRACE_FATAL(thr, pc);
+    ReportReallocArrayOverflow(size, n, &stack);
+  }
+  return user_realloc(thr, pc, p, size * n);
+}
+
 void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write) {
   DPrintf("#%d: alloc(%zu) = %p\n", thr->tid, sz, p);
   ctx->metamap.AllocBlock(thr, pc, p, sz);

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_mman.h Wed May  1 10:33:01 2019
@@ -34,6 +34,7 @@ void user_free(ThreadState *thr, uptr pc
 void *user_alloc(ThreadState *thr, uptr pc, uptr sz);
 void *user_calloc(ThreadState *thr, uptr pc, uptr sz, uptr n);
 void *user_realloc(ThreadState *thr, uptr pc, void *p, uptr sz);
+void *user_reallocarray(ThreadState *thr, uptr pc, void *p, uptr sz, uptr n);
 void *user_memalign(ThreadState *thr, uptr pc, uptr align, uptr sz);
 int user_posix_memalign(ThreadState *thr, uptr pc, void **memptr, uptr align,
                         uptr sz);

Modified: compiler-rt/trunk/test/hwasan/TestCases/realloc-test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/hwasan/TestCases/realloc-test.cc?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/test/hwasan/TestCases/realloc-test.cc (original)
+++ compiler-rt/trunk/test/hwasan/TestCases/realloc-test.cc Wed May  1 10:33:01 2019
@@ -1,36 +1,43 @@
 // Test basic realloc functionality.
-// RUN: %clang_hwasan %s -o %t
-// RUN: %run %t
+// RUN: %clang_hwasan %s -o %t && %run %t
+// RUN: %clang_hwasan %s -DREALLOCARRAY -o %t && %run %t
 
-#include <stdlib.h>
 #include <assert.h>
 #include <sanitizer/hwasan_interface.h>
 
+#ifdef REALLOCARRAY
+extern "C" void *reallocarray(void *, size_t nmemb, size_t size);
+#define REALLOC(p, s) reallocarray(p, 1, s)
+#else
+#include <stdlib.h>
+#define REALLOC(p, s) realloc(p, s)
+#endif
+
 int main() {
   __hwasan_enable_allocator_tagging();
-  char *x = (char*)realloc(nullptr, 4);
+  char *x = (char*)REALLOC(nullptr, 4);
   x[0] = 10;
   x[1] = 20;
   x[2] = 30;
   x[3] = 40;
-  char *x1 = (char*)realloc(x, 5);
+  char *x1 = (char*)REALLOC(x, 5);
   assert(x1 != x);  // not necessary true for C,
                     // but true today for hwasan.
   assert(x1[0] == 10 && x1[1] == 20 && x1[2] == 30 && x1[3] == 40);
   x1[4] = 50;
 
-  char *x2 = (char*)realloc(x1, 6);
+  char *x2 = (char*)REALLOC(x1, 6);
   x2[5] = 60;
   assert(x2 != x1);
   assert(x2[0] == 10 && x2[1] == 20 && x2[2] == 30 && x2[3] == 40 &&
          x2[4] == 50 && x2[5] == 60);
 
-  char *x3 = (char*)realloc(x2, 6);
+  char *x3 = (char*)REALLOC(x2, 6);
   assert(x3 != x2);
   assert(x3[0] == 10 && x3[1] == 20 && x3[2] == 30 && x3[3] == 40 &&
          x3[4] == 50 && x3[5] == 60);
 
-  char *x4 = (char*)realloc(x3, 5);
+  char *x4 = (char*)REALLOC(x3, 5);
   assert(x4 != x3);
   assert(x4[0] == 10 && x4[1] == 20 && x4[2] == 30 && x4[3] == 40 &&
          x4[4] == 50);

Modified: compiler-rt/trunk/test/hwasan/TestCases/sanitizer_malloc.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/hwasan/TestCases/sanitizer_malloc.cc?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/test/hwasan/TestCases/sanitizer_malloc.cc (original)
+++ compiler-rt/trunk/test/hwasan/TestCases/sanitizer_malloc.cc Wed May  1 10:33:01 2019
@@ -20,6 +20,7 @@ int main() {
   sink = (void *)&__sanitizer_malloc_stats;
   sink = (void *)&__sanitizer_calloc;
   sink = (void *)&__sanitizer_realloc;
+  sink = (void *)&__sanitizer_reallocarray;
   sink = (void *)&__sanitizer_malloc;
 
   // sanity check

Modified: compiler-rt/trunk/test/hwasan/TestCases/sizes.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/hwasan/TestCases/sizes.cpp?rev=359708&r1=359707&r2=359708&view=diff
==============================================================================
--- compiler-rt/trunk/test/hwasan/TestCases/sizes.cpp (original)
+++ compiler-rt/trunk/test/hwasan/TestCases/sizes.cpp Wed May  1 10:33:01 2019
@@ -7,6 +7,8 @@
 // RUN: %env_hwasan_opts=allocator_may_return_null=1     %run %t malloc max 2>&1
 // RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t calloc 2>&1          | FileCheck %s --check-prefix=CHECK-calloc
 // RUN: %env_hwasan_opts=allocator_may_return_null=1     %run %t calloc 2>&1
+// RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t reallocarray 2>&1    | FileCheck %s --check-prefix=CHECK-reallocarray
+// RUN: %env_hwasan_opts=allocator_may_return_null=1     %run %t reallocarray 2>&1
 // RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t new 2>&1             | FileCheck %s --check-prefix=CHECK-max
 // RUN: %env_hwasan_opts=allocator_may_return_null=1 not %run %t new 2>&1             | FileCheck %s --check-prefix=CHECK-oom
 // RUN: %env_hwasan_opts=allocator_may_return_null=0 not %run %t new max 2>&1         | FileCheck %s --check-prefix=CHECK-max
@@ -30,6 +32,7 @@
 #include <new>
 
 #include <sanitizer/allocator_interface.h>
+#include <sanitizer/hwasan_interface.h>
 
 int main(int argc, char **argv) {
   assert(argc <= 3);
@@ -51,6 +54,11 @@ int main(int argc, char **argv) {
     size_t size = std::numeric_limits<size_t>::max();
     void *p = calloc((size / 0x1000) + 1, 0x1000);
     assert(!p);
+  } else if (!strcmp(argv[1], "reallocarray")) {
+    // Trigger an overflow in reallocarray.
+    size_t size = std::numeric_limits<size_t>::max();
+    void *p = __sanitizer_reallocarray(nullptr, (size / 0x1000) + 1, 0x1000);
+    assert(!p);
   } else if (!strcmp(argv[1], "new")) {
     void *p = operator new(MallocSize);
     assert(!p);
@@ -80,3 +88,4 @@ 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-calloc: ERROR: HWAddressSanitizer: calloc parameters overflow
+// CHECK-reallocarray: ERROR: HWAddressSanitizer: reallocarray parameters overflow

Added: compiler-rt/trunk/test/sanitizer_common/TestCases/reallocarray-overflow.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/TestCases/reallocarray-overflow.cc?rev=359708&view=auto
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/TestCases/reallocarray-overflow.cc (added)
+++ compiler-rt/trunk/test/sanitizer_common/TestCases/reallocarray-overflow.cc Wed May  1 10:33:01 2019
@@ -0,0 +1,19 @@
+// RUN: %clangxx  -O0 %s -o %t
+// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
+// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
+
+// REQUIRES: stable-runtime && !ubsan && !darwin
+
+#include <stdio.h>
+
+extern "C" void *reallocarray(void *, size_t, size_t);
+
+int main() {
+  void *p = reallocarray(nullptr, -1, 1000);
+  // CHECK: {{ERROR: .*Sanitizer: reallocarray parameters overflow: count \* size \(.* \* 1000\) cannot be represented in type size_t}}
+
+  printf("reallocarray returned: %zu\n", (size_t)p);
+  // CHECK-NULL: reallocarray returned: 0
+
+  return 0;
+}




More information about the llvm-commits mailing list