Skip to content

Commit

Permalink
[msan] Intercept wcscat, wcsncat.
Browse files Browse the repository at this point in the history
Also move wcslen, wscnlen to common interceptors.

Reviewers: vitalybuka

Reviewed By: vitalybuka

Subscribers: kubamracek, llvm-commits

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

llvm-svn: 306482
  • Loading branch information
eugenis committed Jun 27, 2017
1 parent c990236 commit 6f75e2d
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 69 deletions.
11 changes: 0 additions & 11 deletions compiler-rt/lib/asan/asan_interceptors.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
82 changes: 34 additions & 48 deletions compiler-rt/lib/msan/msan_interceptors.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand Down
42 changes: 42 additions & 0 deletions compiler-rt/lib/msan/tests/msan_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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; \
Expand Down
77 changes: 67 additions & 10 deletions compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -6403,4 +6458,6 @@ static void InitializeCommonInterceptors() {
INIT_UTMP;
INIT_UTMPX;
INIT_GETLOADAVG;
INIT_WCSLEN;
INIT_WCSCAT;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 6f75e2d

Please sign in to comment.