Skip to content

[asan][Windows] Add additional wcs* interceptors #66128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions compiler-rt/lib/asan/asan_win_dll_thunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,14 @@ INTERCEPT_LIBRARY_FUNCTION(strstr);
INTERCEPT_LIBRARY_FUNCTION(strtok);
INTERCEPT_LIBRARY_FUNCTION(strtol);
INTERCEPT_LIBRARY_FUNCTION(strtoll);
INTERCEPT_LIBRARY_FUNCTION(wcscat);
INTERCEPT_LIBRARY_FUNCTION(wcschr);
INTERCEPT_LIBRARY_FUNCTION(wcscmp);
INTERCEPT_LIBRARY_FUNCTION(wcscpy);
INTERCEPT_LIBRARY_FUNCTION(wcslen);
INTERCEPT_LIBRARY_FUNCTION(wcsncat);
INTERCEPT_LIBRARY_FUNCTION(wcsncmp);
INTERCEPT_LIBRARY_FUNCTION(wcsncpy);
INTERCEPT_LIBRARY_FUNCTION(wcsnlen);

# if defined(_MSC_VER) && !defined(__clang__)
Expand Down
91 changes: 71 additions & 20 deletions compiler-rt/lib/interception/interception_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -525,15 +525,21 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
switch (*(u16*)(address)) {
case 0x018A: // 8A 01 : mov al, byte ptr [ecx]
case 0xFF8B: // 8B FF : mov edi, edi
case 0xDC8B: // 8B DC : mov ebx, esp
case 0xEC8B: // 8B EC : mov ebp, esp
case 0xc889: // 89 C8 : mov eax, ecx
case 0xE589: // 89 E5 : mov ebp, esp
case 0xC18B: // 8B C1 : mov eax, ecx
case 0xFF33: // 33 FF : xor edi, edi
case 0xC033: // 33 C0 : xor eax, eax
case 0xC933: // 33 C9 : xor ecx, ecx
case 0xD233: // 33 D2 : xor edx, edx
return 2;

case 0xEC83: // 83 EC XX : sub esp, XX
case 0xE483: // 83 E4 XX : and esp, XX
return 3;

// Cannot overwrite control-instruction. Return 0 to indicate failure.
case 0x25FF: // FF 25 XX XX XX XX : jmp [XXXXXXXX]
return 0;
Expand Down Expand Up @@ -577,44 +583,83 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
case 0x018a: // mov al, byte ptr [rcx]
return 2;

case 0xE483: // 83 E4 XX : and esp, XX
case 0xC1F6: // F6 C1 XX : test cl, XX
return 3;

case 0x058B: // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX]
if (rel_offset)
*rel_offset = 2;
return 6;
}

switch (0x00FFFFFF & *(u32*)address) {
case 0xe58948: // 48 8b c4 : mov rbp, rsp
case 0xc18b48: // 48 8b c1 : mov rax, rcx
case 0xc48b48: // 48 8b c4 : mov rax, rsp
case 0xd9f748: // 48 f7 d9 : neg rcx
case 0xd12b48: // 48 2b d1 : sub rdx, rcx
case 0x07c1f6: // f6 c1 07 : test cl, 0x7
case 0xc98548: // 48 85 C9 : test rcx, rcx
case 0xd28548: // 48 85 d2 : test rdx, rdx
case 0xc0854d: // 4d 85 c0 : test r8, r8
case 0xc2b60f: // 0f b6 c2 : movzx eax, dl
case 0xc03345: // 45 33 c0 : xor r8d, r8d
case 0xc93345: // 45 33 c9 : xor r9d, r9d
case 0xdb3345: // 45 33 DB : xor r11d, r11d
case 0xd98b4c: // 4c 8b d9 : mov r11, rcx
case 0xd28b4c: // 4c 8b d2 : mov r10, rdx
case 0xc98b4c: // 4C 8B C9 : mov r9, rcx
case 0xc18b4c: // 4C 8B C1 : mov r8, rcx
case 0xd2b60f: // 0f b6 d2 : movzx edx, dl
case 0xca2b48: // 48 2b ca : sub rcx, rdx
case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]
case 0x01b70f: // 0f b7 01 : movzx eax, word ptr [rcx]
case 0x02b70f: // 0f b7 02 : movzx eax, word ptr [rdx]
case 0x10b70f: // 0f b7 10 : movzx edx, word ptr [rax]
case 0xc2b70f: // 0f b7 c2 : movzx eax, dx
case 0xc00b4d: // 3d 0b c0 : or r8, r8
case 0xc08b41: // 41 8b c0 : mov eax, r8d
case 0xc18b41: // 41 8b c1 : mov eax, r9d
case 0xc28b41: // 41 8b c2 : mov eax, r10d
case 0xc38b41: // 41 8b c3 : mov eax, r11d
case 0xc48b41: // 41 8b c4 : mov eax, r12d
case 0xc03345: // 45 33 c0 : xor r8d, r8d
case 0xc93345: // 45 33 c9 : xor r9d, r9d
case 0xdb3345: // 45 33 db : xor r11d, r11d
case 0xca2b48: // 48 2b ca : sub rcx, rdx
case 0xd12b48: // 48 2b d1 : sub rdx, rcx
case 0xca3b48: // 48 3b ca : cmp rcx, rdx
case 0xc08548: // 48 85 c0 : test rax, rax
case 0xc98548: // 48 85 c9 : test rcx, rcx
case 0xd28548: // 48 85 d2 : test rdx, rdx
case 0xdb8548: // 48 85 db : test rbx, rbx
case 0xe48548: // 48 85 e4 : test rsp, rsp
case 0xed8548: // 48 85 ed : test rbp, rbp
case 0xe58948: // 48 89 e5 : mov rbp, rsp
case 0xc18b48: // 48 8b c1 : mov rax, rcx
case 0xc48b48: // 48 8b c4 : mov rax, rsp
case 0xd18b48: // 48 8b d1 : mov rdx, rcx
case 0xdc8b4c: // 4c 8b dc : mov r11, rsp
case 0xd9f748: // 48 f7 d9 : neg rcx
case 0xc0ff48: // 48 ff c0 : inc rax
case 0xc1ff48: // 48 ff c1 : inc rcx
case 0xc2ff48: // 48 ff c2 : inc rdx
case 0xc3ff48: // 48 ff c3 : inc rbx
case 0xc6ff48: // 48 ff c6 : inc rsi
case 0xc7ff48: // 48 ff c7 : inc rdi
case 0xc0ff49: // 49 ff c0 : inc r8
case 0xc1ff49: // 49 ff c1 : inc r9
case 0xc2ff49: // 49 ff c2 : inc r10
case 0xc3ff49: // 49 ff c3 : inc r11
case 0xc4ff49: // 49 ff c4 : inc r12
case 0xc5ff49: // 49 ff c5 : inc r13
case 0xc6ff49: // 49 ff c6 : inc r14
case 0xc7ff49: // 49 ff c7 : inc r15
case 0xc22b4c: // 4c 2b c2 : sub r8, rdx
case 0xc18b4c: // 4c 8b c1 : mov r8, rcx
case 0xc98b4c: // 4c 8b c9 : mov r9, rcx
case 0xd18b4c: // 4c 8b d1 : mov r10, rcx
case 0xE0E483: // 83 E4 E0 : and esp, 0xFFFFFFE0
case 0xd28b4c: // 4c 8b d2 : mov r10, rdx
case 0xd98b4c: // 4c 8b d9 : mov r11, rcx
case 0xdc8b4c: // 4c 8b dc : mov r11, rsp
case 0xc0854d: // 4d 85 c0 : test r8, r8
case 0xc9854d: // 4d 85 c9 : test r9, r9
case 0xd2854d: // 4d 85 d2 : test r10, r10
case 0xdb854d: // 4d 85 db : test r11, r11
case 0xe4854d: // 4d 85 e4 : test r12, r12
case 0xed854d: // 4d 85 ed : test r13, r13
case 0xf6854d: // 4d 85 f6 : test r14, r14
case 0xff854d: // 4d 85 ff : test r15, r15
return 3;

case 0xec8348: // 48 83 ec XX : sub rsp, XX
case 0xf88349: // 49 83 f8 XX : cmp r8, XX
case 0x588948: // 48 89 58 XX : mov QWORD PTR[rax + XX], rbx
case 0x245489: // 89 54 24 XX : mov DWORD PTR[rsp + XX], edx
case 0x398366: // 66 83 39 XX : cmp DWORD PTR [rcx], XX
case 0x428d44: // 44 8d 42 XX : lea r8d , [rdx + XX]
return 4;

case 0xec8148: // 48 81 EC XX XX XX XX : sub rsp, XXXXXXXX
Expand All @@ -636,6 +681,8 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
}

switch (*(u32*)(address)) {
case 0x01b70f44: // 44 0f b7 01 : movzx r8d, WORD PTR [rcx]
return 4;
case 0x24448b48: // 48 8b 44 24 XX : mov rax, QWORD ptr [rsp + XX]
case 0x246c8948: // 48 89 6C 24 XX : mov QWORD ptr [rsp + XX], rbp
case 0x245c8948: // 48 89 5c 24 XX : mov QWORD PTR [rsp + XX], rbx
Expand All @@ -645,6 +692,10 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
case 0x24548948: // 48 89 54 24 XX : mov QWORD PTR [rsp + XX], rdx
case 0x244c894c: // 4c 89 4c 24 XX : mov QWORD PTR [rsp + XX], r9
case 0x2444894c: // 4c 89 44 24 XX : mov QWORD PTR [rsp + XX], r8
case 0x244c8944: // 44 89 4c 24 XX mov DWORD PTR [rsp + XX], r9d
case 0x24448944: // 44 89 44 24 XX mov DWORD PTR [rsp + XX], r8d
case 0x24548966: // 66 89 54 24 XX : mov [rsp + XX], dx
case 0x246c8d48: // 48 8d 6c 24 XX : lea rbp, [rsp + XX]
return 5;
case 0x24648348: // 48 83 64 24 XX : and QWORD PTR [rsp + XX], YY
return 6;
Expand Down
99 changes: 99 additions & 0 deletions compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,9 @@ INTERCEPTOR(char*, textdomain, const char *domainname) {
static inline int CharCmpX(unsigned char c1, unsigned char c2) {
return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
}
static inline int WCharCmpX(wchar_t c1, wchar_t c2) {
return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
}

DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, uptr called_pc,
const char *s1, const char *s2, int result)
Expand Down Expand Up @@ -7090,6 +7093,99 @@ INTERCEPTOR(wchar_t *, wcsdup, wchar_t *s) {
#define INIT_WCSDUP
#endif

#if SANITIZER_INTERCEPT_WCSCPY
INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dst, const wchar_t *src) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wcscpy, dst, src);
SIZE_T src_len = internal_wcslen(src);
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(wchar_t) * (src_len + 1));
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(wchar_t) * (src_len + 1));
wchar_t *result = internal_wcscpy(dst, src);
return result;
}
INTERCEPTOR(wchar_t *, wcsncpy, wchar_t *dst, const wchar_t *src, SIZE_T size) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wcsncpy, dst, src, size);
SIZE_T src_len = internal_wcsnlen(src, size);
if (src_len != size)
++src_len; // account for the nul terminator
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(wchar_t) * src_len);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(wchar_t) * src_len);
wchar_t *result = internal_wcsncpy(dst, src, size);
return result;
}

#define INIT_WCSCPY \
COMMON_INTERCEPT_FUNCTION(wcscpy); \
COMMON_INTERCEPT_FUNCTION(wcsncpy);
#else
#define INIT_WCSCPY
#endif

#if SANITIZER_INTERCEPT_WCSCMP
INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wcscmp, s1, s2);
wchar_t c1, c2;
uptr i;
for (i = 0;; i++) {
c1 = s1[i];
c2 = s2[i];
if (c1 != c2 || c1 == '\0') break;
}
if (common_flags()->intercept_strcmp) {
COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, sizeof(wchar_t) * (i + 1));
COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, sizeof(wchar_t) * (i + 1));
}
int result = WCharCmpX(c1, c2);
return result;
}
INTERCEPTOR(int, wcsncmp, wchar_t *s1, const wchar_t *s2, SIZE_T size) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wcsncmp, s1, s2, size);
wchar_t c1, c2;
uptr i;
for (i = 0; i < size; i++) {
c1 = s1[i];
c2 = s2[i];
if (c1 != c2 || c1 == '\0') break;
}
uptr i1 = i;
uptr i2 = i;
if (common_flags()->strict_string_checks) {
for (; i1 < size && s1[i1]; i1++) {}
for (; i2 < size && s2[i2]; i2++) {}
}
COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, sizeof(wchar_t) * Min(i1 + 1, size));
COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, sizeof(wchar_t) * Min(i2 + 1, size));
int result = WCharCmpX(c1, c2);
return result;
}

#define INIT_WCSCMP \
COMMON_INTERCEPT_FUNCTION(wcscmp); \
COMMON_INTERCEPT_FUNCTION(wcsncmp);
#else
#define INIT_WCSCMP
#endif

#if SANITIZER_INTERCEPT_WCSCHR
INTERCEPTOR(wchar_t*, wcschr, const wchar_t *s, wchar_t c) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, wcschr, s, c);
wchar_t *result = REAL(wcschr)(s, c);
if (common_flags()->intercept_strchr) {
SIZE_T read_size = (result ? result - s : internal_wcslen(s)) + 1;
COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(*s) * read_size);
}
return result;
}

#define INIT_WCSCHR COMMON_INTERCEPT_FUNCTION(wcschr)
#else
#define INIT_WCSCHR
#endif

#if SANITIZER_INTERCEPT_STRXFRM
static SIZE_T RealStrLen(const char *str) { return internal_strlen(str); }

Expand Down Expand Up @@ -10474,6 +10570,9 @@ static void InitializeCommonInterceptors() {
INIT_WCSLEN;
INIT_WCSCAT;
INIT_WCSDUP;
INIT_WCSCHR;
INIT_WCSCMP;
INIT_WCSCPY;
INIT_WCSXFRM;
INIT___WCSXFRM_L;
INIT_ACCT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -496,8 +496,11 @@
#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD)
#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_WCSLEN 1
#define SANITIZER_INTERCEPT_WCSCAT SI_POSIX
#define SANITIZER_INTERCEPT_WCSCAT (SI_POSIX || SI_WINDOWS)
#define SANITIZER_INTERCEPT_WCSDUP SI_POSIX
#define SANITIZER_INTERCEPT_WCSCPY SI_WINDOWS
#define SANITIZER_INTERCEPT_WCSCMP SI_WINDOWS
#define SANITIZER_INTERCEPT_WCSCHR SI_WINDOWS
#define SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION (!SI_WINDOWS && SI_NOT_FUCHSIA)
#define SANITIZER_INTERCEPT_BSD_SIGNAL SI_ANDROID

Expand Down
Loading