From 8dfc941e62ff9bcb71cfaddffda524674bbb0c53 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Thu, 27 Mar 2014 13:29:29 +0000 Subject: [msan] Intercept several malloc-related functions. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@204923 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/msan/msan_interceptors.cc | 31 ++++++++++++++++++++++ lib/msan/tests/msan_test.cc | 24 ++++++++++------- .../sanitizer_platform_limits_posix.cc | 5 ++++ .../sanitizer_platform_limits_posix.h | 10 +++++++ test/msan/mallinfo.cc | 12 +++++++++ 5 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 test/msan/mallinfo.cc diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc index c4e58d78e..0bac746f2 100644 --- a/lib/msan/msan_interceptors.cc +++ b/lib/msan/msan_interceptors.cc @@ -188,6 +188,32 @@ INTERCEPTOR(void, free, void *ptr) { MsanDeallocate(&stack, ptr); } +INTERCEPTOR(void, cfree, void *ptr) { + GET_MALLOC_STACK_TRACE; + if (ptr == 0) return; + MsanDeallocate(&stack, ptr); +} + +INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { + return __msan_get_allocated_size(ptr); +} + +// This function actually returns a struct by value, but we can't unpoison a +// temporary! The following is equivalent on all supported platforms, and we +// have a test to confirm that. +INTERCEPTOR(void, mallinfo, __sanitizer_mallinfo *sret) { + REAL(memset)(sret, 0, sizeof(*sret)); + __msan_unpoison(sret, sizeof(*sret)); +} + +INTERCEPTOR(int, mallopt, int cmd, int value) { + return -1; +} + +INTERCEPTOR(void, malloc_stats, void) { + // FIXME: implement, but don't call REAL(malloc_stats)! +} + INTERCEPTOR(SIZE_T, strlen, const char *s) { ENSURE_MSAN_INITED(); SIZE_T res = REAL(strlen)(s); @@ -1464,6 +1490,11 @@ void InitializeInterceptors() { INTERCEPT_FUNCTION(calloc); INTERCEPT_FUNCTION(realloc); INTERCEPT_FUNCTION(free); + INTERCEPT_FUNCTION(cfree); + INTERCEPT_FUNCTION(malloc_usable_size); + INTERCEPT_FUNCTION(mallinfo); + INTERCEPT_FUNCTION(mallopt); + INTERCEPT_FUNCTION(malloc_stats); INTERCEPT_FUNCTION(fread); INTERCEPT_FUNCTION(fread_unlocked); INTERCEPT_FUNCTION(readlink); diff --git a/lib/msan/tests/msan_test.cc b/lib/msan/tests/msan_test.cc index 4ffc97505..3ebd211ee 100644 --- a/lib/msan/tests/msan_test.cc +++ b/lib/msan/tests/msan_test.cc @@ -16,6 +16,8 @@ #include "msan_test_config.h" #endif // MSAN_EXTERNAL_TEST_CONFIG +#include "sanitizer_common/tests/sanitizer_test_utils.h" + #include "sanitizer/msan_interface.h" #include "msandr_test_so.h" @@ -174,15 +176,6 @@ T *GetPoisonedO(int i, U4 origin, T val = 0) { return res; } -// This function returns its parameter but in such a way that compiler -// can not prove it. -template -NOINLINE -static T Ident(T t) { - volatile T ret = t; - return ret; -} - template NOINLINE T ReturnPoisoned() { return *GetPoisoned(); } static volatile int g_one = 1; @@ -3880,3 +3873,16 @@ TEST(MemorySanitizer, LargeAllocatorUnpoisonsOnFree) { munmap(q, 4096); } + +#if SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE +TEST(MemorySanitizer, MallocUsableSizeTest) { + const size_t kArraySize = 100; + char *array = Ident((char*)malloc(kArraySize)); + int *int_ptr = Ident(new int); + EXPECT_EQ(0U, malloc_usable_size(NULL)); + EXPECT_EQ(kArraySize, malloc_usable_size(array)); + EXPECT_EQ(sizeof(int), malloc_usable_size(int_ptr)); + free(array); + delete int_ptr; +} +#endif // SANITIZER_TEST_HAS_MALLOC_USABLE_SIZE diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc index 922f44105..cfa9117a6 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -47,6 +47,7 @@ #endif #if SANITIZER_LINUX +#include #include #include #include @@ -1074,4 +1075,8 @@ CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_dstaddr); CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_data); #endif +#if SANITIZER_LINUX +COMPILER_CHECK(sizeof(__sanitizer_mallinfo) == sizeof(struct mallinfo)); +#endif + #endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_MAC diff --git a/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/lib/sanitizer_common/sanitizer_platform_limits_posix.h index 1e2c4da26..0d8fbc88a 100644 --- a/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -138,7 +138,17 @@ namespace __sanitizer { const unsigned old_sigset_t_sz = sizeof(unsigned long); #endif // SANITIZER_LINUX || SANITIZER_FREEBSD +#if SANITIZER_ANDROID + struct __sanitizer_mallinfo { + size_t v[10]; + }; +#endif + #if SANITIZER_LINUX && !SANITIZER_ANDROID + struct __sanitizer_mallinfo { + int v[10]; + }; + extern unsigned struct_ustat_sz; extern unsigned struct_rlimit64_sz; extern unsigned struct_statvfs64_sz; diff --git a/test/msan/mallinfo.cc b/test/msan/mallinfo.cc new file mode 100644 index 000000000..ddd218b7d --- /dev/null +++ b/test/msan/mallinfo.cc @@ -0,0 +1,12 @@ +// RUN: %clangxx_msan -m64 -O0 -g %s -o %t && %t + +#include +#include + +#include + +int main(void) { + struct mallinfo mi = mallinfo(); + assert(__msan_test_shadow(&mi, sizeof(mi)) == -1); + return 0; +} -- cgit v1.2.3