Index: lib/msan/tests/msan_test.cc =================================================================== --- lib/msan/tests/msan_test.cc +++ lib/msan/tests/msan_test.cc @@ -2123,6 +2123,16 @@ EXPECT_EQ(buff[0], 'a'); } +TEST(MemorySanitizer, wctomb) { + wchar_t x = L'a'; + char buff[10]; + wctomb(nullptr, x); + int res = wctomb(buff, x); + EXPECT_EQ(res, 1); + EXPECT_EQ(buff[0], 'a'); + EXPECT_POISONED(buff[1]); +} + TEST(MemorySanitizer, wmemset) { wchar_t x[25]; break_optimization(x); Index: lib/sanitizer_common/sanitizer_common_interceptors.inc =================================================================== --- lib/sanitizer_common/sanitizer_common_interceptors.inc +++ lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -3540,6 +3540,28 @@ #define INIT_WCRTOMB #endif +#if SANITIZER_INTERCEPT_WCTOMB +INTERCEPTOR(int, wctomb, char *dest, wchar_t src) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, wctomb, dest, src); + if (!dest) + return REAL(wctomb)(dest, src); + + char local_dest[32]; + int res = REAL(wctomb)(local_dest, src); + if (res != -1) { + CHECK_LE(res, sizeof(local_dest)); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, res); + REAL(memcpy)(dest, local_dest, res); + } + return res; +} + +#define INIT_WCTOMB COMMON_INTERCEPT_FUNCTION(wctomb); +#else +#define INIT_WCTOMB +#endif + #if SANITIZER_INTERCEPT_TCGETATTR INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) { void *ctx; @@ -9616,6 +9638,7 @@ INIT_WCSTOMBS; INIT_WCSNRTOMBS; INIT_WCRTOMB; + INIT_WCTOMB; INIT_TCGETATTR; INIT_REALPATH; INIT_CANONICALIZE_FILE_NAME; Index: lib/sanitizer_common/sanitizer_platform_interceptors.h =================================================================== --- lib/sanitizer_common/sanitizer_platform_interceptors.h +++ lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -283,6 +283,9 @@ #define SANITIZER_INTERCEPT_WCRTOMB \ (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \ SI_SOLARIS) +#define SANITIZER_INTERCEPT_WCTOMB \ + (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_MAC || SI_LINUX_NOT_ANDROID || \ + SI_SOLARIS) #define SANITIZER_INTERCEPT_TCGETATTR SI_LINUX_NOT_ANDROID || SI_SOLARIS #define SANITIZER_INTERCEPT_REALPATH SI_POSIX #define SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME \ Index: test/sanitizer_common/TestCases/wctomb.c =================================================================== --- /dev/null +++ test/sanitizer_common/TestCases/wctomb.c @@ -0,0 +1,14 @@ +// RUN: %clang %s -o %t && %run %t 2>&1 + +#include +#include + +int main(int argc, char **argv) { + char buff[10]; + wchar_t x = L'a'; + wctomb(NULL, x); + int res = wctomb(buff, x); + assert(res == 1); + assert(buff[0] == 'a'); + return 0; +}