summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEtienne Bergeron <etienneb@google.com>2016-07-14 22:13:41 +0000
committerEtienne Bergeron <etienneb@google.com>2016-07-14 22:13:41 +0000
commit4990a151862569f4b649a8adb4c9eb5700b0fb65 (patch)
treeb31092617bb9b14807cfe3860f5c7d8474deb544
parentb15fb92466378a7d2e67911b89ca77424e57a5c0 (diff)
downloadcompiler-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.cc5
-rw-r--r--lib/sanitizer_common/sanitizer_libc.cc6
-rw-r--r--lib/sanitizer_common/sanitizer_libc.h1
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);