From 0ef67e77cdf42123beefc21cd796315b0e99981a Mon Sep 17 00:00:00 2001 From: Yixuan Cao Date: Mon, 6 Oct 2025 06:49:09 +0800 Subject: [PATCH 1/4] [compiler-rt][asan] Reland: Add wcscpy/wcsncpy; enable wcscat/wcsncat on Windows (#160493) --- compiler-rt/lib/asan/asan_interceptors.cpp | 46 +++++++++++++++++-- compiler-rt/lib/asan/asan_interceptors.h | 1 + .../asan/asan_win_static_runtime_thunk.cpp | 4 ++ .../sanitizer_platform_interceptors.h | 2 +- compiler-rt/test/asan/TestCases/wcscat.cpp | 26 +++++++++++ compiler-rt/test/asan/TestCases/wcscpy.cpp | 23 ++++++++++ compiler-rt/test/asan/TestCases/wcsncat.cpp | 27 +++++++++++ compiler-rt/test/asan/TestCases/wcsncpy.cpp | 25 ++++++++++ 8 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 compiler-rt/test/asan/TestCases/wcscat.cpp create mode 100644 compiler-rt/test/asan/TestCases/wcscpy.cpp create mode 100644 compiler-rt/test/asan/TestCases/wcsncat.cpp create mode 100644 compiler-rt/test/asan/TestCases/wcsncpy.cpp diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp index 7c9a08b9083a2..0f613f0fdc30b 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cpp +++ b/compiler-rt/lib/asan/asan_interceptors.cpp @@ -58,13 +58,20 @@ namespace __asan { static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { #if SANITIZER_INTERCEPT_STRNLEN - if (REAL(strnlen)) { + if (REAL(strnlen)) return REAL(strnlen)(s, maxlen); - } -#endif +# endif return internal_strnlen(s, maxlen); } +static inline uptr MaybeRealWcsnlen(const wchar_t* s, uptr maxlen) { +# if SANITIZER_INTERCEPT_WCSNLEN + if (REAL(wcsnlen)) + return REAL(wcsnlen)(s, maxlen); +# endif + return internal_wcsnlen(s, maxlen); +} + void SetThreadName(const char *name) { AsanThread *t = GetCurrentThread(); if (t) @@ -570,6 +577,20 @@ INTERCEPTOR(char *, strcpy, char *to, const char *from) { return REAL(strcpy)(to, from); } +INTERCEPTOR(wchar_t*, wcscpy, wchar_t* to, const wchar_t* from) { + void* ctx; + ASAN_INTERCEPTOR_ENTER(ctx, wcscpy); + if (!TryAsanInitFromRtl()) + return REAL(wcscpy)(to, from); + if (flags()->replace_str) { + uptr size = (internal_wcslen(from) + 1) * sizeof(wchar_t); + CHECK_RANGES_OVERLAP("wcscpy", to, size, from, size); + ASAN_READ_RANGE(ctx, from, size); + ASAN_WRITE_RANGE(ctx, to, size); + } + return REAL(wcscpy)(to, from); +} + // Windows doesn't always define the strdup identifier, // and when it does it's a macro defined to either _strdup // or _strdup_dbg, _strdup_dbg ends up calling _strdup, so @@ -633,6 +654,20 @@ INTERCEPTOR(char*, strncpy, char *to, const char *from, usize size) { return REAL(strncpy)(to, from, size); } +INTERCEPTOR(wchar_t*, wcsncpy, wchar_t* to, const wchar_t* from, uptr size) { + void* ctx; + ASAN_INTERCEPTOR_ENTER(ctx, wcsncpy); + AsanInitFromRtl(); + if (flags()->replace_str) { + uptr from_size = + Min(size, MaybeRealWcsnlen(from, size) + 1) * sizeof(wchar_t); + CHECK_RANGES_OVERLAP("wcsncpy", to, from_size, from, from_size); + ASAN_READ_RANGE(ctx, from, from_size); + ASAN_WRITE_RANGE(ctx, to, size * sizeof(wchar_t)); + } + return REAL(wcsncpy)(to, from, size); +} + template static ALWAYS_INLINE auto StrtolImpl(void *ctx, Fn real, const char *nptr, char **endptr, int base) @@ -809,6 +844,11 @@ void InitializeAsanInterceptors() { ASAN_INTERCEPT_FUNC(strncat); ASAN_INTERCEPT_FUNC(strncpy); ASAN_INTERCEPT_FUNC(strdup); + + // Intercept wcs* functions. + ASAN_INTERCEPT_FUNC(wcscpy); + ASAN_INTERCEPT_FUNC(wcsncpy); + # if ASAN_INTERCEPT___STRDUP ASAN_INTERCEPT_FUNC(__strdup); #endif diff --git a/compiler-rt/lib/asan/asan_interceptors.h b/compiler-rt/lib/asan/asan_interceptors.h index 3e2386eaf8092..2d551cfafd1f5 100644 --- a/compiler-rt/lib/asan/asan_interceptors.h +++ b/compiler-rt/lib/asan/asan_interceptors.h @@ -129,6 +129,7 @@ DECLARE_REAL(char*, strchr, const char *str, int c) DECLARE_REAL(SIZE_T, strlen, const char *s) DECLARE_REAL(char*, strncpy, char *to, const char *from, SIZE_T size) DECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen) +DECLARE_REAL(SIZE_T, wcsnlen, const wchar_t* s, SIZE_T maxlen) DECLARE_REAL(char*, strstr, const char *s1, const char *s2) # if !SANITIZER_APPLE diff --git a/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp b/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp index 4a69b66574039..46e0e90738f24 100644 --- a/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp +++ b/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp @@ -63,6 +63,10 @@ INTERCEPT_LIBRARY_FUNCTION_ASAN(strpbrk); INTERCEPT_LIBRARY_FUNCTION_ASAN(strspn); INTERCEPT_LIBRARY_FUNCTION_ASAN(strstr); INTERCEPT_LIBRARY_FUNCTION_ASAN(strtok); +INTERCEPT_LIBRARY_FUNCTION_ASAN(wcscat); +INTERCEPT_LIBRARY_FUNCTION_ASAN(wcscpy); +INTERCEPT_LIBRARY_FUNCTION_ASAN(wcsncat); +INTERCEPT_LIBRARY_FUNCTION_ASAN(wcsncpy); INTERCEPT_LIBRARY_FUNCTION_ASAN(wcslen); INTERCEPT_LIBRARY_FUNCTION_ASAN(wcsnlen); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 29987decdff45..88ecd7e16306a 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -551,7 +551,7 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #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_SIGNAL_AND_SIGACTION (!SI_WINDOWS && SI_NOT_FUCHSIA) #define SANITIZER_INTERCEPT_BSD_SIGNAL SI_ANDROID diff --git a/compiler-rt/test/asan/TestCases/wcscat.cpp b/compiler-rt/test/asan/TestCases/wcscat.cpp new file mode 100644 index 0000000000000..dcdff88c18ef1 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/wcscat.cpp @@ -0,0 +1,26 @@ +// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK + +#include +#include + +int main() { + wchar_t *start = L"X means "; + wchar_t *append = L"dog"; + wchar_t goodDst[12]; + wcscpy(goodDst, start); + wcscat(goodDst, append); + + wchar_t badDst[9]; + wcscpy(badDst, start); + printf("Good so far.\n"); + // CHECK: Good so far. + fflush(stdout); + wcscat(badDst, append); // Boom! + // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} + // CHECK: WRITE of size {{[0-9]+}} at [[ADDR:0x[0-9a-f]+]] thread T0 + // CHECK: #0 [[ADDR:0x[0-9a-f]+]] in wcscat{{.*}}sanitizer_common_interceptors.inc:{{[0-9]+}} + printf("Should have failed with ASAN error.\n"); +} \ No newline at end of file diff --git a/compiler-rt/test/asan/TestCases/wcscpy.cpp b/compiler-rt/test/asan/TestCases/wcscpy.cpp new file mode 100644 index 0000000000000..414d83303a960 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/wcscpy.cpp @@ -0,0 +1,23 @@ +// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK + +#include +#include + +int main() { + wchar_t *src = L"X means dog"; + wchar_t goodDst[12]; + wcscpy(goodDst, src); + + wchar_t badDst[7]; + printf("Good so far.\n"); + // CHECK: Good so far. + fflush(stdout); + wcscpy(badDst, src); // Boom! + // CHECK:ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} + // CHECK: WRITE of size {{[0-9]+}} at [[ADDR:0x[0-9a-f]+]] thread T0 + // CHECK: #0 [[ADDR:0x[0-9a-f]+]] in wcscpy{{.*}}asan_interceptors.cpp:{{[0-9]+}} + printf("Should have failed with ASAN error.\n"); +} \ No newline at end of file diff --git a/compiler-rt/test/asan/TestCases/wcsncat.cpp b/compiler-rt/test/asan/TestCases/wcsncat.cpp new file mode 100644 index 0000000000000..3ab7fc8f55d63 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/wcsncat.cpp @@ -0,0 +1,27 @@ +// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK + +#include +#include + +int main() { + wchar_t *start = L"X means "; + wchar_t *append = L"dog"; + wchar_t goodDst[15]; + wcscpy(goodDst, start); + wcsncat(goodDst, append, 5); + + wchar_t badDst[11]; + wcscpy(badDst, start); + wcsncat(badDst, append, 1); + printf("Good so far.\n"); + // CHECK: Good so far. + fflush(stdout); + wcsncat(badDst, append, 3); // Boom! + // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} + // CHECK: WRITE of size {{[0-9]+}} at [[ADDR:0x[0-9a-f]+]] thread T0 + // CHECK: #0 [[ADDR:0x[0-9a-f]+]] in wcsncat{{.*}}sanitizer_common_interceptors.inc:{{[0-9]+}} + printf("Should have failed with ASAN error.\n"); +} \ No newline at end of file diff --git a/compiler-rt/test/asan/TestCases/wcsncpy.cpp b/compiler-rt/test/asan/TestCases/wcsncpy.cpp new file mode 100644 index 0000000000000..6177b72990a0a --- /dev/null +++ b/compiler-rt/test/asan/TestCases/wcsncpy.cpp @@ -0,0 +1,25 @@ +// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK + +#include +#include + +int main() { + wchar_t *src = L"X means dog"; + wchar_t goodDst[12]; + wcsncpy(goodDst, src, 12); + + wchar_t badDst[7]; + wcsncpy(badDst, src, 7); // This should still work. + printf("Good so far.\n"); + // CHECK: Good so far. + fflush(stdout); + + wcsncpy(badDst, src, 15); // Boom! + // CHECK:ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} + // CHECK: WRITE of size {{[0-9]+}} at [[ADDR:0x[0-9a-f]+]] thread T0 + // CHECK: #0 [[ADDR:0x[0-9a-f]+]] in wcsncpy{{.*}}asan_interceptors.cpp:{{[0-9]+}} + printf("Should have failed with ASAN error.\n"); +} \ No newline at end of file From 373cca4d8546f9239efe084ca74e8bdf3156478c Mon Sep 17 00:00:00 2001 From: Yixuan Cao Date: Mon, 6 Oct 2025 06:49:34 +0800 Subject: [PATCH 2/4] [compiler-rt][asan][tests] Reland: Stabilize wchar tests on Darwin/Android (#161624) --- compiler-rt/test/asan/TestCases/wcscat.cpp | 20 ++++++++++---------- compiler-rt/test/asan/TestCases/wcscpy.cpp | 20 ++++++++++---------- compiler-rt/test/asan/TestCases/wcsncat.cpp | 20 ++++++++++---------- compiler-rt/test/asan/TestCases/wcsncpy.cpp | 20 ++++++++++---------- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/compiler-rt/test/asan/TestCases/wcscat.cpp b/compiler-rt/test/asan/TestCases/wcscat.cpp index dcdff88c18ef1..f0a8ec12580b3 100644 --- a/compiler-rt/test/asan/TestCases/wcscat.cpp +++ b/compiler-rt/test/asan/TestCases/wcscat.cpp @@ -1,26 +1,26 @@ -// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK -// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK -// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK -// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O0 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O1 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O2 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O3 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK #include #include int main() { - wchar_t *start = L"X means "; - wchar_t *append = L"dog"; + const wchar_t *start = L"X means "; + const wchar_t *append = L"dog"; wchar_t goodDst[12]; wcscpy(goodDst, start); wcscat(goodDst, append); wchar_t badDst[9]; wcscpy(badDst, start); - printf("Good so far.\n"); + fprintf(stderr, "Good so far.\n"); // CHECK: Good so far. - fflush(stdout); + fflush(stderr); wcscat(badDst, append); // Boom! // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} - // CHECK: WRITE of size {{[0-9]+}} at [[ADDR:0x[0-9a-f]+]] thread T0 - // CHECK: #0 [[ADDR:0x[0-9a-f]+]] in wcscat{{.*}}sanitizer_common_interceptors.inc:{{[0-9]+}} + // CHECK: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 + // CHECK: #0 {{0x[0-9a-f]+}} in wcscat printf("Should have failed with ASAN error.\n"); } \ No newline at end of file diff --git a/compiler-rt/test/asan/TestCases/wcscpy.cpp b/compiler-rt/test/asan/TestCases/wcscpy.cpp index 414d83303a960..a280d29289e37 100644 --- a/compiler-rt/test/asan/TestCases/wcscpy.cpp +++ b/compiler-rt/test/asan/TestCases/wcscpy.cpp @@ -1,23 +1,23 @@ -// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK -// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK -// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK -// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O0 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O1 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O2 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O3 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK #include #include int main() { - wchar_t *src = L"X means dog"; + const wchar_t *src = L"X means dog"; wchar_t goodDst[12]; wcscpy(goodDst, src); wchar_t badDst[7]; - printf("Good so far.\n"); + fprintf(stderr, "Good so far.\n"); // CHECK: Good so far. - fflush(stdout); + fflush(stderr); wcscpy(badDst, src); // Boom! - // CHECK:ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} - // CHECK: WRITE of size {{[0-9]+}} at [[ADDR:0x[0-9a-f]+]] thread T0 - // CHECK: #0 [[ADDR:0x[0-9a-f]+]] in wcscpy{{.*}}asan_interceptors.cpp:{{[0-9]+}} + // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} + // CHECK: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 + // CHECK: #0 {{0x[0-9a-f]+}} in wcscpy printf("Should have failed with ASAN error.\n"); } \ No newline at end of file diff --git a/compiler-rt/test/asan/TestCases/wcsncat.cpp b/compiler-rt/test/asan/TestCases/wcsncat.cpp index 3ab7fc8f55d63..eb7d095e45c7a 100644 --- a/compiler-rt/test/asan/TestCases/wcsncat.cpp +++ b/compiler-rt/test/asan/TestCases/wcsncat.cpp @@ -1,14 +1,14 @@ -// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK -// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK -// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK -// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O0 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O1 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O2 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O3 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK #include #include int main() { - wchar_t *start = L"X means "; - wchar_t *append = L"dog"; + const wchar_t *start = L"X means "; + const wchar_t *append = L"dog"; wchar_t goodDst[15]; wcscpy(goodDst, start); wcsncat(goodDst, append, 5); @@ -16,12 +16,12 @@ int main() { wchar_t badDst[11]; wcscpy(badDst, start); wcsncat(badDst, append, 1); - printf("Good so far.\n"); + fprintf(stderr, "Good so far.\n"); // CHECK: Good so far. - fflush(stdout); + fflush(stderr); wcsncat(badDst, append, 3); // Boom! // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} - // CHECK: WRITE of size {{[0-9]+}} at [[ADDR:0x[0-9a-f]+]] thread T0 - // CHECK: #0 [[ADDR:0x[0-9a-f]+]] in wcsncat{{.*}}sanitizer_common_interceptors.inc:{{[0-9]+}} + // CHECK: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 + // CHECK: #0 {{0x[0-9a-f]+}} in wcsncat printf("Should have failed with ASAN error.\n"); } \ No newline at end of file diff --git a/compiler-rt/test/asan/TestCases/wcsncpy.cpp b/compiler-rt/test/asan/TestCases/wcsncpy.cpp index 6177b72990a0a..1106bf5d264e5 100644 --- a/compiler-rt/test/asan/TestCases/wcsncpy.cpp +++ b/compiler-rt/test/asan/TestCases/wcsncpy.cpp @@ -1,25 +1,25 @@ -// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK -// RUN: %clangxx_asan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK -// RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK -// RUN: %clangxx_asan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O0 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O1 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O2 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_asan -O3 %s -o %t && not %env_asan_opts=log_to_stderr=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK #include #include int main() { - wchar_t *src = L"X means dog"; + const wchar_t *src = L"X means dog"; wchar_t goodDst[12]; wcsncpy(goodDst, src, 12); wchar_t badDst[7]; wcsncpy(badDst, src, 7); // This should still work. - printf("Good so far.\n"); + fprintf(stderr, "Good so far.\n"); // CHECK: Good so far. - fflush(stdout); + fflush(stderr); wcsncpy(badDst, src, 15); // Boom! - // CHECK:ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} - // CHECK: WRITE of size {{[0-9]+}} at [[ADDR:0x[0-9a-f]+]] thread T0 - // CHECK: #0 [[ADDR:0x[0-9a-f]+]] in wcsncpy{{.*}}asan_interceptors.cpp:{{[0-9]+}} + // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} + // CHECK: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 + // CHECK: #0 {{0x[0-9a-f]+}} in wcsncpy printf("Should have failed with ASAN error.\n"); } \ No newline at end of file From 304e76e6b60995d366e8efd597a53df8360a8ef6 Mon Sep 17 00:00:00 2001 From: Yixuan Cao Date: Mon, 6 Oct 2025 06:51:47 +0800 Subject: [PATCH 3/4] Darwin: tolerate reordering using DAG group --- compiler-rt/test/asan/TestCases/wcscat.cpp | 8 ++++---- compiler-rt/test/asan/TestCases/wcscpy.cpp | 8 ++++---- compiler-rt/test/asan/TestCases/wcsncat.cpp | 8 ++++---- compiler-rt/test/asan/TestCases/wcsncpy.cpp | 9 ++++----- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/compiler-rt/test/asan/TestCases/wcscat.cpp b/compiler-rt/test/asan/TestCases/wcscat.cpp index f0a8ec12580b3..833dee9655264 100644 --- a/compiler-rt/test/asan/TestCases/wcscat.cpp +++ b/compiler-rt/test/asan/TestCases/wcscat.cpp @@ -16,11 +16,11 @@ int main() { wchar_t badDst[9]; wcscpy(badDst, start); fprintf(stderr, "Good so far.\n"); - // CHECK: Good so far. + // CHECK-DAG: Good so far. fflush(stderr); wcscat(badDst, append); // Boom! - // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} - // CHECK: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 - // CHECK: #0 {{0x[0-9a-f]+}} in wcscat + // CHECK-DAG: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} + // CHECK-DAG: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 + // CHECK-DAG: #0 {{0x[0-9a-f]+}} in wcscat printf("Should have failed with ASAN error.\n"); } \ No newline at end of file diff --git a/compiler-rt/test/asan/TestCases/wcscpy.cpp b/compiler-rt/test/asan/TestCases/wcscpy.cpp index a280d29289e37..c7205e486e3ff 100644 --- a/compiler-rt/test/asan/TestCases/wcscpy.cpp +++ b/compiler-rt/test/asan/TestCases/wcscpy.cpp @@ -13,11 +13,11 @@ int main() { wchar_t badDst[7]; fprintf(stderr, "Good so far.\n"); - // CHECK: Good so far. + // CHECK-DAG: Good so far. fflush(stderr); wcscpy(badDst, src); // Boom! - // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} - // CHECK: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 - // CHECK: #0 {{0x[0-9a-f]+}} in wcscpy + // CHECK-DAG: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} + // CHECK-DAG: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 + // CHECK-DAG: #0 {{0x[0-9a-f]+}} in wcscpy printf("Should have failed with ASAN error.\n"); } \ No newline at end of file diff --git a/compiler-rt/test/asan/TestCases/wcsncat.cpp b/compiler-rt/test/asan/TestCases/wcsncat.cpp index eb7d095e45c7a..8fe1e510a26cf 100644 --- a/compiler-rt/test/asan/TestCases/wcsncat.cpp +++ b/compiler-rt/test/asan/TestCases/wcsncat.cpp @@ -17,11 +17,11 @@ int main() { wcscpy(badDst, start); wcsncat(badDst, append, 1); fprintf(stderr, "Good so far.\n"); - // CHECK: Good so far. + // CHECK-DAG: Good so far. fflush(stderr); wcsncat(badDst, append, 3); // Boom! - // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} - // CHECK: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 - // CHECK: #0 {{0x[0-9a-f]+}} in wcsncat + // CHECK-DAG: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} + // CHECK-DAG: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 + // CHECK-DAG: #0 {{0x[0-9a-f]+}} in wcsncat printf("Should have failed with ASAN error.\n"); } \ No newline at end of file diff --git a/compiler-rt/test/asan/TestCases/wcsncpy.cpp b/compiler-rt/test/asan/TestCases/wcsncpy.cpp index 1106bf5d264e5..7db3351cdb6a6 100644 --- a/compiler-rt/test/asan/TestCases/wcsncpy.cpp +++ b/compiler-rt/test/asan/TestCases/wcsncpy.cpp @@ -14,12 +14,11 @@ int main() { wchar_t badDst[7]; wcsncpy(badDst, src, 7); // This should still work. fprintf(stderr, "Good so far.\n"); - // CHECK: Good so far. + // CHECK-DAG: Good so far. fflush(stderr); - wcsncpy(badDst, src, 15); // Boom! - // CHECK: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} - // CHECK: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 - // CHECK: #0 {{0x[0-9a-f]+}} in wcsncpy + // CHECK-DAG: ERROR: AddressSanitizer: stack-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] at pc {{0x[0-9a-f]+}} bp {{0x[0-9a-f]+}} sp {{0x[0-9a-f]+}} + // CHECK-DAG: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 + // CHECK-DAG: #0 {{0x[0-9a-f]+}} in wcsncpy printf("Should have failed with ASAN error.\n"); } \ No newline at end of file From aabcf185b9c2c0e59ed1079b60785b5b806e89af Mon Sep 17 00:00:00 2001 From: Yixuan Cao Date: Mon, 6 Oct 2025 07:52:21 +0800 Subject: [PATCH 4/4] Fix: add trailing newlines to wcs*.cpp Signed-off-by: Yixuan Cao --- compiler-rt/test/asan/TestCases/wcscat.cpp | 2 +- compiler-rt/test/asan/TestCases/wcscpy.cpp | 2 +- compiler-rt/test/asan/TestCases/wcsncat.cpp | 2 +- compiler-rt/test/asan/TestCases/wcsncpy.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler-rt/test/asan/TestCases/wcscat.cpp b/compiler-rt/test/asan/TestCases/wcscat.cpp index 833dee9655264..fd0b5a4310351 100644 --- a/compiler-rt/test/asan/TestCases/wcscat.cpp +++ b/compiler-rt/test/asan/TestCases/wcscat.cpp @@ -23,4 +23,4 @@ int main() { // CHECK-DAG: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 // CHECK-DAG: #0 {{0x[0-9a-f]+}} in wcscat printf("Should have failed with ASAN error.\n"); -} \ No newline at end of file +} diff --git a/compiler-rt/test/asan/TestCases/wcscpy.cpp b/compiler-rt/test/asan/TestCases/wcscpy.cpp index c7205e486e3ff..8133a588cb071 100644 --- a/compiler-rt/test/asan/TestCases/wcscpy.cpp +++ b/compiler-rt/test/asan/TestCases/wcscpy.cpp @@ -20,4 +20,4 @@ int main() { // CHECK-DAG: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 // CHECK-DAG: #0 {{0x[0-9a-f]+}} in wcscpy printf("Should have failed with ASAN error.\n"); -} \ No newline at end of file +} diff --git a/compiler-rt/test/asan/TestCases/wcsncat.cpp b/compiler-rt/test/asan/TestCases/wcsncat.cpp index 8fe1e510a26cf..365e732e2d051 100644 --- a/compiler-rt/test/asan/TestCases/wcsncat.cpp +++ b/compiler-rt/test/asan/TestCases/wcsncat.cpp @@ -24,4 +24,4 @@ int main() { // CHECK-DAG: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 // CHECK-DAG: #0 {{0x[0-9a-f]+}} in wcsncat printf("Should have failed with ASAN error.\n"); -} \ No newline at end of file +} diff --git a/compiler-rt/test/asan/TestCases/wcsncpy.cpp b/compiler-rt/test/asan/TestCases/wcsncpy.cpp index 7db3351cdb6a6..485ddc4804dcd 100644 --- a/compiler-rt/test/asan/TestCases/wcsncpy.cpp +++ b/compiler-rt/test/asan/TestCases/wcsncpy.cpp @@ -21,4 +21,4 @@ int main() { // CHECK-DAG: WRITE of size {{[0-9]+}} at [[ADDR]] thread T0 // CHECK-DAG: #0 {{0x[0-9a-f]+}} in wcsncpy printf("Should have failed with ASAN error.\n"); -} \ No newline at end of file +}