From 711bea9dedd81cffa4d04dc6bb9edee933e04aaf Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Fri, 29 Mar 2019 08:39:03 +0000 Subject: [PATCH] [Sanitizer] Add interceptor for wctomb Summary: This is required to avoid msan false positives for code using this function (although generally one should avoid using this function in favor of wcrtomb). Reviewers: eugenis, EricWF, vitalybuka Subscribers: srhines, kubamracek, fedor.sergeev, delcypher, llvm-commits, #sanitizers Tags: #llvm, #sanitizers Differential Revision: https://reviews.llvm.org/D59548 llvm-svn: 357240 --- compiler-rt/lib/msan/tests/msan_test.cc | 10 ++++++++++ .../sanitizer_common_interceptors.inc | 23 ++++++++++++++++++++++ .../sanitizer_platform_interceptors.h | 3 +++ .../test/sanitizer_common/TestCases/wctomb.c | 14 +++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 compiler-rt/test/sanitizer_common/TestCases/wctomb.c diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc index d2002d1..9d2f5a7 100644 --- a/compiler-rt/lib/msan/tests/msan_test.cc +++ b/compiler-rt/lib/msan/tests/msan_test.cc @@ -2123,6 +2123,16 @@ TEST(MemorySanitizer, wcrtomb) { 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); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 4ea274f..b3be48d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -3540,6 +3540,28 @@ INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) { #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 @@ static void InitializeCommonInterceptors() { INIT_WCSTOMBS; INIT_WCSNRTOMBS; INIT_WCRTOMB; + INIT_WCTOMB; INIT_TCGETATTR; INIT_REALPATH; INIT_CANONICALIZE_FILE_NAME; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index a4116f8..3cbdd01 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/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 \ diff --git a/compiler-rt/test/sanitizer_common/TestCases/wctomb.c b/compiler-rt/test/sanitizer_common/TestCases/wctomb.c new file mode 100644 index 0000000..87089d2 --- /dev/null +++ b/compiler-rt/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; +} -- 2.7.4