From 233455cba845004af5c59cc8a456a8199cf85521 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Thu, 8 Aug 2013 11:44:05 +0000 Subject: [PATCH] [sanitizer] Intercept strerror and strerror_r. llvm-svn: 187978 --- compiler-rt/lib/msan/tests/msan_test.cc | 16 +++++++ .../sanitizer_common_interceptors.inc | 44 ++++++++++++++++++- .../sanitizer_platform_interceptors.h | 2 + compiler-rt/lib/tsan/rtl/tsan_stat.cc | 2 + compiler-rt/lib/tsan/rtl/tsan_stat.h | 2 + 5 files changed, 65 insertions(+), 1 deletion(-) diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc index aa1e8ebeac83..f8e5622e8c01 100644 --- a/compiler-rt/lib/msan/tests/msan_test.cc +++ b/compiler-rt/lib/msan/tests/msan_test.cc @@ -544,6 +544,22 @@ TEST(MemorySanitizer, LargeRet) { EXPECT_POISONED(a.x[9]); } +TEST(MemorySanitizer, strerror) { + char *buf = strerror(EINVAL); + EXPECT_NOT_POISONED(strlen(buf)); + buf = strerror(123456); + EXPECT_NOT_POISONED(strlen(buf)); +} + +TEST(MemorySanitizer, strerror_r) { + errno = 0; + char buf[1000]; + char *res = strerror_r(EINVAL, buf, sizeof(buf)); + ASSERT_EQ(0, errno); + if (!res) res = buf; // POSIX version success. + EXPECT_NOT_POISONED(strlen(res)); +} + TEST(MemorySanitizer, fread) { char *x = new char[32]; FILE *f = fopen("/proc/self/stat", "r"); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index bf99141788b5..31f389cb20bc 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -1776,6 +1776,46 @@ INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) { #define INIT_SCHED_GETAFFINITY #endif +#if SANITIZER_INTERCEPT_STRERROR +INTERCEPTOR(char *, strerror, int errnum) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum); + char *res = REAL(strerror)(errnum); + if (res) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + return res; +} +#define INIT_STRERROR INTERCEPT_FUNCTION(strerror); +#else +#define INIT_STRERROR +#endif + +#if SANITIZER_INTERCEPT_STRERROR_R +INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen); + char *res = REAL(strerror_r)(errnum, buf, buflen); + // There are 2 versions of strerror_r: + // * POSIX version returns 0 on success, negative error code on failure, + // writes message to buf. + // * GNU version returns message pointer, which points to either buf or some + // static storage. + if (!res) { + // POSIX version. Spec is not clear on whether buf is NULL-terminated. + SIZE_T sz = internal_strnlen(buf, buflen); + if (sz < buflen) ++sz; + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz); + } else if ((SIZE_T)res < (SIZE_T) - 1024) { + // GNU version. + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1); + } + return res; +} +#define INIT_STRERROR_R INTERCEPT_FUNCTION(strerror_r); +#else +#define INIT_STRERROR_R +#endif + #define SANITIZER_COMMON_INTERCEPTORS_INIT \ INIT_STRCMP; \ INIT_STRNCMP; \ @@ -1836,4 +1876,6 @@ INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) { INIT_REALPATH; \ INIT_CANONICALIZE_FILE_NAME; \ INIT_CONFSTR; \ - INIT_SCHED_GETAFFINITY; + INIT_SCHED_GETAFFINITY; \ + INIT_STRERROR; \ + INIT_STRERROR_R; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index e3aaf211f362..033678ae022f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -111,5 +111,7 @@ # define SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME SI_LINUX_NOT_ANDROID # define SANITIZER_INTERCEPT_CONFSTR SI_MAC || SI_LINUX_NOT_ANDROID # define SANITIZER_INTERCEPT_SCHED_GETAFFINITY SI_LINUX_NOT_ANDROID +# define SANITIZER_INTERCEPT_STRERROR SI_NOT_WINDOWS +# define SANITIZER_INTERCEPT_STRERROR_R SI_NOT_WINDOWS #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.cc b/compiler-rt/lib/tsan/rtl/tsan_stat.cc index dacc498d92d3..2640dd56e286 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_stat.cc @@ -354,6 +354,8 @@ void StatOutput(u64 *stat) { name[StatInt_canonicalize_file_name] = " canonicalize_file_name "; name[StatInt_confstr] = " confstr "; name[StatInt_sched_getaffinity] = " sched_getaffinity "; + name[StatInt_strerror] = " strerror "; + name[StatInt_strerror_r] = " strerror_r "; name[StatAnnotation] = "Dynamic annotations "; name[StatAnnotateHappensBefore] = " HappensBefore "; diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.h b/compiler-rt/lib/tsan/rtl/tsan_stat.h index b3a850a03f00..68aae3fa5b67 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.h +++ b/compiler-rt/lib/tsan/rtl/tsan_stat.h @@ -349,6 +349,8 @@ enum StatType { StatInt_canonicalize_file_name, StatInt_confstr, StatInt_sched_getaffinity, + StatInt_strerror, + StatInt_strerror_r, // Dynamic annotations. StatAnnotation, -- 2.34.1