Skip to content

Commit 8d5b48e

Browse files
committed
Add moar wcs* interceptions
wcs[n]cat, wcs[n]cmp, wcs[n]cpy, and wcschr wcs[n]cat already existed, but only on POSIX
1 parent 6a45339 commit 8d5b48e

File tree

5 files changed

+418
-21
lines changed

5 files changed

+418
-21
lines changed

compiler-rt/lib/asan/asan_win_dll_thunk.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,14 @@ INTERCEPT_LIBRARY_FUNCTION(strstr);
9393
INTERCEPT_LIBRARY_FUNCTION(strtok);
9494
INTERCEPT_LIBRARY_FUNCTION(strtol);
9595
INTERCEPT_LIBRARY_FUNCTION(strtoll);
96+
INTERCEPT_LIBRARY_FUNCTION(wcscat);
97+
INTERCEPT_LIBRARY_FUNCTION(wcschr);
98+
INTERCEPT_LIBRARY_FUNCTION(wcscmp);
99+
INTERCEPT_LIBRARY_FUNCTION(wcscpy);
96100
INTERCEPT_LIBRARY_FUNCTION(wcslen);
101+
INTERCEPT_LIBRARY_FUNCTION(wcsncat);
102+
INTERCEPT_LIBRARY_FUNCTION(wcsncmp);
103+
INTERCEPT_LIBRARY_FUNCTION(wcsncpy);
97104
INTERCEPT_LIBRARY_FUNCTION(wcsnlen);
98105

99106
# if defined(_MSC_VER) && !defined(__clang__)

compiler-rt/lib/interception/interception_win.cpp

Lines changed: 71 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -525,15 +525,21 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
525525
switch (*(u16*)(address)) {
526526
case 0x018A: // 8A 01 : mov al, byte ptr [ecx]
527527
case 0xFF8B: // 8B FF : mov edi, edi
528+
case 0xDC8B: // 8B DC : mov ebx, esp
528529
case 0xEC8B: // 8B EC : mov ebp, esp
529530
case 0xc889: // 89 C8 : mov eax, ecx
530531
case 0xE589: // 89 E5 : mov ebp, esp
531532
case 0xC18B: // 8B C1 : mov eax, ecx
533+
case 0xFF33: // 33 FF : xor edi, edi
532534
case 0xC033: // 33 C0 : xor eax, eax
533535
case 0xC933: // 33 C9 : xor ecx, ecx
534536
case 0xD233: // 33 D2 : xor edx, edx
535537
return 2;
536538

539+
case 0xEC83: // 83 EC XX : sub esp, XX
540+
case 0xE483: // 83 E4 XX : and esp, XX
541+
return 3;
542+
537543
// Cannot overwrite control-instruction. Return 0 to indicate failure.
538544
case 0x25FF: // FF 25 XX XX XX XX : jmp [XXXXXXXX]
539545
return 0;
@@ -577,44 +583,83 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
577583
case 0x018a: // mov al, byte ptr [rcx]
578584
return 2;
579585

586+
case 0xE483: // 83 E4 XX : and esp, XX
587+
case 0xC1F6: // F6 C1 XX : test cl, XX
588+
return 3;
589+
580590
case 0x058B: // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX]
581591
if (rel_offset)
582592
*rel_offset = 2;
583593
return 6;
584594
}
585595

586596
switch (0x00FFFFFF & *(u32*)address) {
587-
case 0xe58948: // 48 8b c4 : mov rbp, rsp
588-
case 0xc18b48: // 48 8b c1 : mov rax, rcx
589-
case 0xc48b48: // 48 8b c4 : mov rax, rsp
590-
case 0xd9f748: // 48 f7 d9 : neg rcx
591-
case 0xd12b48: // 48 2b d1 : sub rdx, rcx
592-
case 0x07c1f6: // f6 c1 07 : test cl, 0x7
593-
case 0xc98548: // 48 85 C9 : test rcx, rcx
594-
case 0xd28548: // 48 85 d2 : test rdx, rdx
595-
case 0xc0854d: // 4d 85 c0 : test r8, r8
596597
case 0xc2b60f: // 0f b6 c2 : movzx eax, dl
597-
case 0xc03345: // 45 33 c0 : xor r8d, r8d
598-
case 0xc93345: // 45 33 c9 : xor r9d, r9d
599-
case 0xdb3345: // 45 33 DB : xor r11d, r11d
600-
case 0xd98b4c: // 4c 8b d9 : mov r11, rcx
601-
case 0xd28b4c: // 4c 8b d2 : mov r10, rdx
602-
case 0xc98b4c: // 4C 8B C9 : mov r9, rcx
603-
case 0xc18b4c: // 4C 8B C1 : mov r8, rcx
604598
case 0xd2b60f: // 0f b6 d2 : movzx edx, dl
605-
case 0xca2b48: // 48 2b ca : sub rcx, rdx
606-
case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]
599+
case 0x01b70f: // 0f b7 01 : movzx eax, word ptr [rcx]
600+
case 0x02b70f: // 0f b7 02 : movzx eax, word ptr [rdx]
601+
case 0x10b70f: // 0f b7 10 : movzx edx, word ptr [rax]
602+
case 0xc2b70f: // 0f b7 c2 : movzx eax, dx
607603
case 0xc00b4d: // 3d 0b c0 : or r8, r8
608604
case 0xc08b41: // 41 8b c0 : mov eax, r8d
605+
case 0xc18b41: // 41 8b c1 : mov eax, r9d
606+
case 0xc28b41: // 41 8b c2 : mov eax, r10d
607+
case 0xc38b41: // 41 8b c3 : mov eax, r11d
608+
case 0xc48b41: // 41 8b c4 : mov eax, r12d
609+
case 0xc03345: // 45 33 c0 : xor r8d, r8d
610+
case 0xc93345: // 45 33 c9 : xor r9d, r9d
611+
case 0xdb3345: // 45 33 db : xor r11d, r11d
612+
case 0xca2b48: // 48 2b ca : sub rcx, rdx
613+
case 0xd12b48: // 48 2b d1 : sub rdx, rcx
614+
case 0xca3b48: // 48 3b ca : cmp rcx, rdx
615+
case 0xc08548: // 48 85 c0 : test rax, rax
616+
case 0xc98548: // 48 85 c9 : test rcx, rcx
617+
case 0xd28548: // 48 85 d2 : test rdx, rdx
618+
case 0xdb8548: // 48 85 db : test rbx, rbx
619+
case 0xe48548: // 48 85 e4 : test rsp, rsp
620+
case 0xed8548: // 48 85 ed : test rbp, rbp
621+
case 0xe58948: // 48 89 e5 : mov rbp, rsp
622+
case 0xc18b48: // 48 8b c1 : mov rax, rcx
623+
case 0xc48b48: // 48 8b c4 : mov rax, rsp
609624
case 0xd18b48: // 48 8b d1 : mov rdx, rcx
610-
case 0xdc8b4c: // 4c 8b dc : mov r11, rsp
625+
case 0xd9f748: // 48 f7 d9 : neg rcx
626+
case 0xc0ff48: // 48 ff c0 : inc rax
627+
case 0xc1ff48: // 48 ff c1 : inc rcx
628+
case 0xc2ff48: // 48 ff c2 : inc rdx
629+
case 0xc3ff48: // 48 ff c3 : inc rbx
630+
case 0xc6ff48: // 48 ff c6 : inc rsi
631+
case 0xc7ff48: // 48 ff c7 : inc rdi
632+
case 0xc0ff49: // 49 ff c0 : inc r8
633+
case 0xc1ff49: // 49 ff c1 : inc r9
634+
case 0xc2ff49: // 49 ff c2 : inc r10
635+
case 0xc3ff49: // 49 ff c3 : inc r11
636+
case 0xc4ff49: // 49 ff c4 : inc r12
637+
case 0xc5ff49: // 49 ff c5 : inc r13
638+
case 0xc6ff49: // 49 ff c6 : inc r14
639+
case 0xc7ff49: // 49 ff c7 : inc r15
640+
case 0xc22b4c: // 4c 2b c2 : sub r8, rdx
641+
case 0xc18b4c: // 4c 8b c1 : mov r8, rcx
642+
case 0xc98b4c: // 4c 8b c9 : mov r9, rcx
611643
case 0xd18b4c: // 4c 8b d1 : mov r10, rcx
612-
case 0xE0E483: // 83 E4 E0 : and esp, 0xFFFFFFE0
644+
case 0xd28b4c: // 4c 8b d2 : mov r10, rdx
645+
case 0xd98b4c: // 4c 8b d9 : mov r11, rcx
646+
case 0xdc8b4c: // 4c 8b dc : mov r11, rsp
647+
case 0xc0854d: // 4d 85 c0 : test r8, r8
648+
case 0xc9854d: // 4d 85 c9 : test r9, r9
649+
case 0xd2854d: // 4d 85 d2 : test r10, r10
650+
case 0xdb854d: // 4d 85 db : test r11, r11
651+
case 0xe4854d: // 4d 85 e4 : test r12, r12
652+
case 0xed854d: // 4d 85 ed : test r13, r13
653+
case 0xf6854d: // 4d 85 f6 : test r14, r14
654+
case 0xff854d: // 4d 85 ff : test r15, r15
613655
return 3;
614656

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

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

638683
switch (*(u32*)(address)) {
684+
case 0x01b70f44: // 44 0f b7 01 : movzx r8d, WORD PTR [rcx]
685+
return 4;
639686
case 0x24448b48: // 48 8b 44 24 XX : mov rax, QWORD ptr [rsp + XX]
640687
case 0x246c8948: // 48 89 6C 24 XX : mov QWORD ptr [rsp + XX], rbp
641688
case 0x245c8948: // 48 89 5c 24 XX : mov QWORD PTR [rsp + XX], rbx
@@ -645,6 +692,10 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
645692
case 0x24548948: // 48 89 54 24 XX : mov QWORD PTR [rsp + XX], rdx
646693
case 0x244c894c: // 4c 89 4c 24 XX : mov QWORD PTR [rsp + XX], r9
647694
case 0x2444894c: // 4c 89 44 24 XX : mov QWORD PTR [rsp + XX], r8
695+
case 0x244c8944: // 44 89 4c 24 XX mov DWORD PTR [rsp + XX], r9d
696+
case 0x24448944: // 44 89 44 24 XX mov DWORD PTR [rsp + XX], r8d
697+
case 0x24548966: // 66 89 54 24 XX : mov [rsp + XX], dx
698+
case 0x246c8d48: // 48 8d 6c 24 XX : lea rbp, [rsp + XX]
648699
return 5;
649700
case 0x24648348: // 48 83 64 24 XX : and QWORD PTR [rsp + XX], YY
650701
return 6;

compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,9 @@ INTERCEPTOR(char*, textdomain, const char *domainname) {
449449
static inline int CharCmpX(unsigned char c1, unsigned char c2) {
450450
return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
451451
}
452+
static inline int WCharCmpX(wchar_t c1, wchar_t c2) {
453+
return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
454+
}
452455

453456
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, uptr called_pc,
454457
const char *s1, const char *s2, int result)
@@ -7090,6 +7093,99 @@ INTERCEPTOR(wchar_t *, wcsdup, wchar_t *s) {
70907093
#define INIT_WCSDUP
70917094
#endif
70927095

7096+
#if SANITIZER_INTERCEPT_WCSCPY
7097+
INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dst, const wchar_t *src) {
7098+
void *ctx;
7099+
COMMON_INTERCEPTOR_ENTER(ctx, wcscpy, dst, src);
7100+
SIZE_T src_len = internal_wcslen(src);
7101+
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(wchar_t) * (src_len + 1));
7102+
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(wchar_t) * (src_len + 1));
7103+
wchar_t *result = internal_wcscpy(dst, src);
7104+
return result;
7105+
}
7106+
INTERCEPTOR(wchar_t *, wcsncpy, wchar_t *dst, const wchar_t *src, SIZE_T size) {
7107+
void *ctx;
7108+
COMMON_INTERCEPTOR_ENTER(ctx, wcsncpy, dst, src, size);
7109+
SIZE_T src_len = internal_wcsnlen(src, size);
7110+
if (src_len != size)
7111+
++src_len; // account for the nul terminator
7112+
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(wchar_t) * src_len);
7113+
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(wchar_t) * src_len);
7114+
wchar_t *result = internal_wcsncpy(dst, src, size);
7115+
return result;
7116+
}
7117+
7118+
#define INIT_WCSCPY \
7119+
COMMON_INTERCEPT_FUNCTION(wcscpy); \
7120+
COMMON_INTERCEPT_FUNCTION(wcsncpy);
7121+
#else
7122+
#define INIT_WCSCPY
7123+
#endif
7124+
7125+
#if SANITIZER_INTERCEPT_WCSCMP
7126+
INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) {
7127+
void *ctx;
7128+
COMMON_INTERCEPTOR_ENTER(ctx, wcscmp, s1, s2);
7129+
wchar_t c1, c2;
7130+
uptr i;
7131+
for (i = 0;; i++) {
7132+
c1 = s1[i];
7133+
c2 = s2[i];
7134+
if (c1 != c2 || c1 == '\0') break;
7135+
}
7136+
if (common_flags()->intercept_strcmp) {
7137+
COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, sizeof(wchar_t) * (i + 1));
7138+
COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, sizeof(wchar_t) * (i + 1));
7139+
}
7140+
int result = WCharCmpX(c1, c2);
7141+
return result;
7142+
}
7143+
INTERCEPTOR(int, wcsncmp, wchar_t *s1, const wchar_t *s2, SIZE_T size) {
7144+
void *ctx;
7145+
COMMON_INTERCEPTOR_ENTER(ctx, wcsncmp, s1, s2, size);
7146+
wchar_t c1, c2;
7147+
uptr i;
7148+
for (i = 0; i < size; i++) {
7149+
c1 = s1[i];
7150+
c2 = s2[i];
7151+
if (c1 != c2 || c1 == '\0') break;
7152+
}
7153+
uptr i1 = i;
7154+
uptr i2 = i;
7155+
if (common_flags()->strict_string_checks) {
7156+
for (; i1 < size && s1[i1]; i1++) {}
7157+
for (; i2 < size && s2[i2]; i2++) {}
7158+
}
7159+
COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, sizeof(wchar_t) * Min(i1 + 1, size));
7160+
COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, sizeof(wchar_t) * Min(i2 + 1, size));
7161+
int result = WCharCmpX(c1, c2);
7162+
return result;
7163+
}
7164+
7165+
#define INIT_WCSCMP \
7166+
COMMON_INTERCEPT_FUNCTION(wcscmp); \
7167+
COMMON_INTERCEPT_FUNCTION(wcsncmp);
7168+
#else
7169+
#define INIT_WCSCMP
7170+
#endif
7171+
7172+
#if SANITIZER_INTERCEPT_WCSCHR
7173+
INTERCEPTOR(wchar_t*, wcschr, const wchar_t *s, wchar_t c) {
7174+
void *ctx;
7175+
COMMON_INTERCEPTOR_ENTER(ctx, wcschr, s, c);
7176+
wchar_t *result = REAL(wcschr)(s, c);
7177+
if (common_flags()->intercept_strchr) {
7178+
SIZE_T read_size = (result ? result - s : internal_wcslen(s)) + 1;
7179+
COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(*s) * read_size);
7180+
}
7181+
return result;
7182+
}
7183+
7184+
#define INIT_WCSCHR COMMON_INTERCEPT_FUNCTION(wcschr)
7185+
#else
7186+
#define INIT_WCSCHR
7187+
#endif
7188+
70937189
#if SANITIZER_INTERCEPT_STRXFRM
70947190
static SIZE_T RealStrLen(const char *str) { return internal_strlen(str); }
70957191

@@ -10474,6 +10570,9 @@ static void InitializeCommonInterceptors() {
1047410570
INIT_WCSLEN;
1047510571
INIT_WCSCAT;
1047610572
INIT_WCSDUP;
10573+
INIT_WCSCHR;
10574+
INIT_WCSCMP;
10575+
INIT_WCSCPY;
1047710576
INIT_WCSXFRM;
1047810577
INIT___WCSXFRM_L;
1047910578
INIT_ACCT;

compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,8 +496,11 @@
496496
#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD)
497497
#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
498498
#define SANITIZER_INTERCEPT_WCSLEN 1
499-
#define SANITIZER_INTERCEPT_WCSCAT SI_POSIX
499+
#define SANITIZER_INTERCEPT_WCSCAT (SI_POSIX || SI_WINDOWS)
500500
#define SANITIZER_INTERCEPT_WCSDUP SI_POSIX
501+
#define SANITIZER_INTERCEPT_WCSCPY SI_WINDOWS
502+
#define SANITIZER_INTERCEPT_WCSCMP SI_WINDOWS
503+
#define SANITIZER_INTERCEPT_WCSCHR SI_WINDOWS
501504
#define SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION (!SI_WINDOWS && SI_NOT_FUCHSIA)
502505
#define SANITIZER_INTERCEPT_BSD_SIGNAL SI_ANDROID
503506

0 commit comments

Comments
 (0)