summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/asan/asan_allocator.cc2
-rw-r--r--compiler-rt/lib/asan/asan_allocator2.cc1
-rw-r--r--compiler-rt/lib/asan/tests/asan_noinst_test.cc9
-rw-r--r--compiler-rt/lib/msan/msan_interceptors.cc2
-rw-r--r--compiler-rt/lib/msan/tests/msan_test.cc8
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc5
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_allocator.h3
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_interceptors.cc1
-rw-r--r--compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc10
9 files changed, 41 insertions, 0 deletions
diff --git a/compiler-rt/lib/asan/asan_allocator.cc b/compiler-rt/lib/asan/asan_allocator.cc
index 30dd4ceddd8..370307a89cc 100644
--- a/compiler-rt/lib/asan/asan_allocator.cc
+++ b/compiler-rt/lib/asan/asan_allocator.cc
@@ -35,6 +35,7 @@
#include "asan_thread.h"
#include "asan_thread_registry.h"
#include "sanitizer/asan_interface.h"
+#include "sanitizer_common/sanitizer_allocator.h"
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_mutex.h"
@@ -712,6 +713,7 @@ void *asan_malloc(uptr size, StackTrace *stack) {
}
void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
+ if (__sanitizer::CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
void *ptr = (void*)Allocate(0, nmemb * size, stack, FROM_MALLOC);
if (ptr)
REAL(memset)(ptr, 0, nmemb * size);
diff --git a/compiler-rt/lib/asan/asan_allocator2.cc b/compiler-rt/lib/asan/asan_allocator2.cc
index 7bfa5fd24b2..184627a586a 100644
--- a/compiler-rt/lib/asan/asan_allocator2.cc
+++ b/compiler-rt/lib/asan/asan_allocator2.cc
@@ -607,6 +607,7 @@ void *asan_malloc(uptr size, StackTrace *stack) {
}
void *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
+ if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC);
if (ptr)
REAL(memset)(ptr, 0, nmemb * size);
diff --git a/compiler-rt/lib/asan/tests/asan_noinst_test.cc b/compiler-rt/lib/asan/tests/asan_noinst_test.cc
index b7b4a4bab89..95ad15e2cc3 100644
--- a/compiler-rt/lib/asan/tests/asan_noinst_test.cc
+++ b/compiler-rt/lib/asan/tests/asan_noinst_test.cc
@@ -25,6 +25,7 @@
#include <string.h> // for memset()
#include <algorithm>
#include <vector>
+#include <limits>
TEST(AddressSanitizer, InternalSimpleDeathTest) {
@@ -831,3 +832,11 @@ TEST(AddressSanitizerInterface, GetOwnershipStressTest) {
for (size_t i = 0, n = pointers.size(); i < n; i++)
free(pointers[i]);
}
+
+TEST(AddressSanitizerInterface, CallocOverflow) {
+ size_t kArraySize = 4096;
+ volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max();
+ volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
+ void *p = calloc(kArraySize, kArraySize2); // Should return 0.
+ EXPECT_EQ(0L, Ident(p));
+}
diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc
index 67c872fef62..0672bcf78c9 100644
--- a/compiler-rt/lib/msan/msan_interceptors.cc
+++ b/compiler-rt/lib/msan/msan_interceptors.cc
@@ -18,6 +18,7 @@
#include "interception/interception.h"
#include "msan.h"
#include "msan_platform_limits_posix.h"
+#include "sanitizer_common/sanitizer_allocator.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
@@ -683,6 +684,7 @@ INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct msghdr *msg, int flags) {
}
INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
+ if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
GET_MALLOC_STACK_TRACE;
if (!msan_inited) {
// Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc
index f65d6f9bff7..09bdf503c18 100644
--- a/compiler-rt/lib/msan/tests/msan_test.cc
+++ b/compiler-rt/lib/msan/tests/msan_test.cc
@@ -1685,6 +1685,14 @@ NOINLINE void RecursiveMalloc(int depth) {
delete x2;
}
+TEST(MemorySanitizer, CallocOverflow) {
+ size_t kArraySize = 4096;
+ volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max();
+ volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
+ void *p = calloc(kArraySize, kArraySize2); // Should return 0.
+ EXPECT_EQ(0L, Ident(p));
+}
+
TEST(MemorySanitizerStress, DISABLED_MallocStackTrace) {
RecursiveMalloc(22);
}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc
index b13a7c6c14c..26baf73a1f3 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cc
@@ -75,4 +75,9 @@ void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback) {
low_level_alloc_callback = callback;
}
+bool CallocShouldReturnNullDueToOverflow(uptr size, uptr n) {
+ uptr mul = size * n;
+ return mul < size || mul < n;
+}
+
} // namespace __sanitizer
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h
index 1ca7c9a3e1c..39c20b9624d 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.h
@@ -1098,6 +1098,9 @@ class CombinedAllocator {
AllocatorGlobalStats stats_;
};
+// Returns true if calloc(size, n) should return 0 due to overflow in size*n.
+bool CallocShouldReturnNullDueToOverflow(uptr size, uptr n);
+
} // namespace __sanitizer
#endif // SANITIZER_ALLOCATOR_H
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
index be58ca92cf9..3fc38453376 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
@@ -326,6 +326,7 @@ TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) {
}
TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) {
+ if (__sanitizer::CallocShouldReturnNullDueToOverflow(size, n)) return 0;
void *p = 0;
{
SCOPED_INTERCEPTOR_RAW(calloc, size, n);
diff --git a/compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc b/compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc
index 988918fff59..af813a2ca5f 100644
--- a/compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc
+++ b/compiler-rt/lib/tsan/tests/unit/tsan_mman_test.cc
@@ -10,6 +10,7 @@
// This file is a part of ThreadSanitizer (TSan), a race detector.
//
//===----------------------------------------------------------------------===//
+#include <limits>
#include "tsan_mman.h"
#include "tsan_rtl.h"
#include "gtest/gtest.h"
@@ -145,4 +146,13 @@ TEST(Mman, Stats) {
EXPECT_EQ(__tsan_get_free_bytes(), free0);
EXPECT_EQ(__tsan_get_unmapped_bytes(), unmapped0);
}
+
+TEST(Mman, CallocOverflow) {
+ size_t kArraySize = 4096;
+ volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max();
+ volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
+ volatile void *p = calloc(kArraySize, kArraySize2); // Should return 0.
+ EXPECT_EQ(0L, p);
+}
+
} // namespace __tsan
OpenPOWER on IntegriCloud