From 054ff981e8e285ba623c9255f2ecc52263f0e03a Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Tue, 27 Jun 2017 22:52:38 +0000 Subject: [msan] Intercept wcscat, wcsncat. Also move wcslen, wscnlen to common interceptors. Reviewers: vitalybuka Reviewed By: vitalybuka Subscribers: kubamracek, llvm-commits Differential Revision: https://reviews.llvm.org/D34656 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@306482 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/asan/asan_interceptors.cc | 11 --- lib/msan/msan_interceptors.cc | 82 +++++++++------------- lib/msan/tests/msan_test.cc | 42 +++++++++++ .../sanitizer_common_interceptors.inc | 77 +++++++++++++++++--- .../sanitizer_platform_interceptors.h | 2 + 5 files changed, 145 insertions(+), 69 deletions(-) (limited to 'lib') diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc index 264d5aee8..e03c0f94c 100644 --- a/lib/asan/asan_interceptors.cc +++ b/lib/asan/asan_interceptors.cc @@ -579,17 +579,6 @@ INTERCEPTOR(char*, __strdup, const char *s) { } #endif // ASAN_INTERCEPT___STRDUP -INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) { - void *ctx; - ASAN_INTERCEPTOR_ENTER(ctx, wcslen); - SIZE_T length = internal_wcslen(s); - if (!asan_init_is_running) { - ENSURE_ASAN_INITED(); - ASAN_READ_RANGE(ctx, s, (length + 1) * sizeof(wchar_t)); - } - return length; -} - INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strncpy); diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc index 0f5069344..ce8444a3b 100644 --- a/lib/msan/msan_interceptors.cc +++ b/lib/msan/msan_interceptors.cc @@ -538,49 +538,6 @@ INTERCEPTOR(int, mbrtowc, wchar_t *dest, const char *src, SIZE_T n, void *ps) { return res; } -INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) { - ENSURE_MSAN_INITED(); - SIZE_T res = REAL(wcslen)(s); - CHECK_UNPOISONED(s, sizeof(wchar_t) * (res + 1)); - return res; -} - -INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) { - ENSURE_MSAN_INITED(); - SIZE_T res = REAL(wcsnlen)(s, n); - CHECK_UNPOISONED(s, sizeof(wchar_t) * Min(res + 1, n)); - return res; -} - -// wchar_t *wcschr(const wchar_t *wcs, wchar_t wc); -INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) { - ENSURE_MSAN_INITED(); - wchar_t *res = REAL(wcschr)(s, wc, ps); - return res; -} - -// wchar_t *wcscpy(wchar_t *dest, const wchar_t *src); -INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) { - ENSURE_MSAN_INITED(); - GET_STORE_STACK_TRACE; - wchar_t *res = REAL(wcscpy)(dest, src); - CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1), - &stack); - return res; -} - -INTERCEPTOR(wchar_t *, wcsncpy, wchar_t *dest, const wchar_t *src, - SIZE_T n) { // NOLINT - ENSURE_MSAN_INITED(); - GET_STORE_STACK_TRACE; - SIZE_T copy_size = REAL(wcsnlen)(src, n); - if (copy_size < n) copy_size++; // trailing \0 - wchar_t *res = REAL(wcsncpy)(dest, src, n); // NOLINT - CopyShadowAndOrigin(dest, src, copy_size * sizeof(wchar_t), &stack); - __msan_unpoison(dest + copy_size, (n - copy_size) * sizeof(wchar_t)); - return res; -} - // wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n); INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) { ENSURE_MSAN_INITED(); @@ -1344,11 +1301,11 @@ int OnExit() { return __msan_memcpy(to, from, size); \ } -#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \ - do { \ - GET_STORE_STACK_TRACE; \ - CopyShadowAndOrigin(to, from, size, &stack); \ - __msan_unpoison(to + size, 1); \ +#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \ + do { \ + GET_STORE_STACK_TRACE; \ + CopyShadowAndOrigin(to, from, size, &stack); \ + __msan_unpoison(to + size, 1); \ } while (false) #include "sanitizer_common/sanitizer_platform_interceptors.h" @@ -1424,6 +1381,35 @@ INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) { return res; } +// wchar_t *wcschr(const wchar_t *wcs, wchar_t wc); +INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) { + ENSURE_MSAN_INITED(); + wchar_t *res = REAL(wcschr)(s, wc, ps); + return res; +} + +// wchar_t *wcscpy(wchar_t *dest, const wchar_t *src); +INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) { + ENSURE_MSAN_INITED(); + GET_STORE_STACK_TRACE; + wchar_t *res = REAL(wcscpy)(dest, src); + CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1), + &stack); + return res; +} + +INTERCEPTOR(wchar_t *, wcsncpy, wchar_t *dest, const wchar_t *src, + SIZE_T n) { // NOLINT + ENSURE_MSAN_INITED(); + GET_STORE_STACK_TRACE; + SIZE_T copy_size = REAL(wcsnlen)(src, n); + if (copy_size < n) copy_size++; // trailing \0 + wchar_t *res = REAL(wcsncpy)(dest, src, n); // NOLINT + CopyShadowAndOrigin(dest, src, copy_size * sizeof(wchar_t), &stack); + __msan_unpoison(dest + copy_size, (n - copy_size) * sizeof(wchar_t)); + return res; +} + // These interface functions reside here so that they can use // REAL(memset), etc. void __msan_unpoison(const void *a, uptr size) { diff --git a/lib/msan/tests/msan_test.cc b/lib/msan/tests/msan_test.cc index 543a7eb98..b2d5f7c60 100644 --- a/lib/msan/tests/msan_test.cc +++ b/lib/msan/tests/msan_test.cc @@ -1707,6 +1707,48 @@ TEST(MemorySanitizer, strncat_overflow) { // NOLINT EXPECT_POISONED(a[7]); } +TEST(MemorySanitizer, wcscat) { + wchar_t a[10]; + wchar_t b[] = L"def"; + wcscpy(a, L"abc"); + + wcscat(a, b); + EXPECT_EQ(6U, wcslen(a)); + EXPECT_POISONED(a[7]); + + a[3] = 0; + __msan_poison(b + 1, sizeof(wchar_t)); + EXPECT_UMR(wcscat(a, b)); + + __msan_unpoison(b + 1, sizeof(wchar_t)); + __msan_poison(a + 2, sizeof(wchar_t)); + EXPECT_UMR(wcscat(a, b)); +} + +TEST(MemorySanitizer, wcsncat) { + wchar_t a[10]; + wchar_t b[] = L"def"; + wcscpy(a, L"abc"); + + wcsncat(a, b, 5); + EXPECT_EQ(6U, wcslen(a)); + EXPECT_POISONED(a[7]); + + a[3] = 0; + __msan_poison(a + 4, sizeof(wchar_t) * 6); + wcsncat(a, b, 2); + EXPECT_EQ(5U, wcslen(a)); + EXPECT_POISONED(a[6]); + + a[3] = 0; + __msan_poison(b + 1, sizeof(wchar_t)); + EXPECT_UMR(wcsncat(a, b, 2)); + + __msan_unpoison(b + 1, sizeof(wchar_t)); + __msan_poison(a + 2, sizeof(wchar_t)); + EXPECT_UMR(wcsncat(a, b, 2)); +} + #define TEST_STRTO_INT(func_name, char_type, str_prefix) \ TEST(MemorySanitizer, func_name) { \ char_type *e; \ diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc index 6ca431d8a..af7de6759 100644 --- a/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -224,16 +224,16 @@ bool PlatformHasDifferentMemcpyAndMemmove(); #endif #ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL -#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size) \ - COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size); \ - uptr copy_length = internal_strnlen(s, size); \ - char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \ - if (common_flags()->intercept_strndup) { \ - COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1)); \ - } \ - COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \ - internal_memcpy(new_mem, s, copy_length); \ - new_mem[copy_length] = '\0'; \ +#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size) \ + COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size); \ + uptr copy_length = internal_strnlen(s, size); \ + char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \ + if (common_flags()->intercept_strndup) { \ + COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1)); \ + } \ + COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \ + internal_memcpy(new_mem, s, copy_length); \ + new_mem[copy_length] = '\0'; \ return new_mem; #endif @@ -6199,6 +6199,61 @@ INTERCEPTOR(int, mprobe, void *ptr) { } #endif +#if SANITIZER_INTERCEPT_WCSLEN +INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, wcslen, s); + SIZE_T res = REAL(wcslen)(s); + COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (res + 1)); + return res; +} + +INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, wcsnlen, s, n); + SIZE_T res = REAL(wcsnlen)(s, n); + COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * Min(res + 1, n)); + return res; +} +#define INIT_WCSLEN \ + COMMON_INTERCEPT_FUNCTION(wcslen); \ + COMMON_INTERCEPT_FUNCTION(wcsnlen); +#else +#define INIT_WCSLEN +#endif + +#if SANITIZER_INTERCEPT_WCSCAT +INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, wcscat, dst, src); + SIZE_T src_size = REAL(wcslen)(src); + SIZE_T dst_size = REAL(wcslen)(dst); + COMMON_INTERCEPTOR_READ_RANGE(ctx, src, (src_size + 1) * sizeof(wchar_t)); + COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size, + (src_size + 1) * sizeof(wchar_t)); + return REAL(wcscat)(dst, src); // NOLINT +} + +INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, wcsncat, dst, src, n); + SIZE_T src_size = REAL(wcsnlen)(src, n); + SIZE_T dst_size = REAL(wcslen)(dst); + COMMON_INTERCEPTOR_READ_RANGE(ctx, src, + Min(src_size + 1, n) * sizeof(wchar_t)); + COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size, + (src_size + 1) * sizeof(wchar_t)); + return REAL(wcsncat)(dst, src, n); // NOLINT +} +#define INIT_WCSCAT \ + COMMON_INTERCEPT_FUNCTION(wcscat); \ + COMMON_INTERCEPT_FUNCTION(wcsncat); +#else +#define INIT_WCSCAT +#endif + static void InitializeCommonInterceptors() { static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1]; interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap(); @@ -6403,4 +6458,6 @@ static void InitializeCommonInterceptors() { INIT_UTMP; INIT_UTMPX; INIT_GETLOADAVG; + INIT_WCSLEN; + INIT_WCSCAT; } diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h index a95497467..da683c62f 100644 --- a/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -354,5 +354,7 @@ #define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC) #define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC) #define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID +#define SANITIZER_INTERCEPT_WCSLEN SI_NOT_WINDOWS +#define SANITIZER_INTERCEPT_WCSCAT SI_NOT_WINDOWS #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H -- cgit v1.2.3