diff options
author | Etienne Bergeron <etienneb@google.com> | 2016-07-14 22:13:41 +0000 |
---|---|---|
committer | Etienne Bergeron <etienneb@google.com> | 2016-07-14 22:13:41 +0000 |
commit | 4990a151862569f4b649a8adb4c9eb5700b0fb65 (patch) | |
tree | b31092617bb9b14807cfe3860f5c7d8474deb544 | |
parent | b15fb92466378a7d2e67911b89ca77424e57a5c0 (diff) | |
download | compiler-rt-4990a151862569f4b649a8adb4c9eb5700b0fb65.tar.gz |
[compiler-rt] Add internal wcslen to avoid crashing on windows 64-bits
Summary:
The function wcslen is incorrectly hooked on windows 64-bits.
The interception library is not able to hook without breaking the code.
The function is too small and the interception must be done with
trampoline-hooking which turned out to be incorrect on a small
loop (first few instructions have a backedge).
Reviewers: rnk
Subscribers: wang0109, chrisha, llvm-commits, kubabrecka
Differential Revision: https://reviews.llvm.org/D22363
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@275488 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/asan/asan_interceptors.cc | 5 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_libc.cc | 6 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_libc.h | 1 |
3 files changed, 12 insertions, 0 deletions
diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc index 3b3b0f380..79a6e9c7c 100644 --- a/lib/asan/asan_interceptors.cc +++ b/lib/asan/asan_interceptors.cc @@ -585,7 +585,12 @@ INTERCEPTOR(char*, __strdup, const char *s) { INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, wcslen); +#if SANITIZER_WINDOWS64 + // The function is incorrectly hooked on windows 64-bit. + SIZE_T length = internal_wcslen(s); +#else SIZE_T length = REAL(wcslen)(s); +#endif if (!asan_init_is_running) { ENSURE_ASAN_INITED(); ASAN_READ_RANGE(ctx, s, (length + 1) * sizeof(wchar_t)); diff --git a/lib/sanitizer_common/sanitizer_libc.cc b/lib/sanitizer_common/sanitizer_libc.cc index 28f55ddd9..d6c8ea2a1 100644 --- a/lib/sanitizer_common/sanitizer_libc.cc +++ b/lib/sanitizer_common/sanitizer_libc.cc @@ -234,6 +234,12 @@ char *internal_strstr(const char *haystack, const char *needle) { return nullptr; } +uptr internal_wcslen(const wchar_t *s) { + uptr i = 0; + while (s[i]) i++; + return i; +} + s64 internal_simple_strtoll(const char *nptr, char **endptr, int base) { CHECK_EQ(base, 10); while (IsSpace(*nptr)) nptr++; diff --git a/lib/sanitizer_common/sanitizer_libc.h b/lib/sanitizer_common/sanitizer_libc.h index 71b891772..155bbc49a 100644 --- a/lib/sanitizer_common/sanitizer_libc.h +++ b/lib/sanitizer_common/sanitizer_libc.h @@ -51,6 +51,7 @@ char *internal_strncpy(char *dst, const char *src, uptr n); uptr internal_strnlen(const char *s, uptr maxlen); char *internal_strrchr(const char *s, int c); // This is O(N^2), but we are not using it in hot places. +uptr internal_wcslen(const wchar_t *s); char *internal_strstr(const char *haystack, const char *needle); // Works only for base=10 and doesn't set errno. s64 internal_simple_strtoll(const char *nptr, char **endptr, int base); |