[sanitizer] Intercept strerror and strerror_r.
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Thu, 8 Aug 2013 11:44:05 +0000 (11:44 +0000)
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Thu, 8 Aug 2013 11:44:05 +0000 (11:44 +0000)
llvm-svn: 187978

compiler-rt/lib/msan/tests/msan_test.cc
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
compiler-rt/lib/tsan/rtl/tsan_stat.cc
compiler-rt/lib/tsan/rtl/tsan_stat.h

index aa1e8ebeac83c24dd832d320022a0feae841d529..f8e5622e8c014d47e97d77223a4ddf5e53c95d15 100644 (file)
@@ -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");
index bf99141788b570a46faf441617bcf35f70bd5b3c..31f389cb20bc492a66afbce275147c06ee49d2ee 100644 (file)
@@ -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;
index e3aaf211f36289ebcbcf613a057889f07f5f14a8..033678ae022fce3523c57bd7006196c9f7b5804d 100644 (file)
 # 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
index dacc498d92d3096694c12179e351b57ab67e9e21..2640dd56e286f96382bbd01bdd3466ff3769c594 100644 (file)
@@ -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                   ";
index b3a850a03f00dfc804ffd5d62a4d5bdb47fd34f6..68aae3fa5b674f0c37eef2aa89f5a515ce549425 100644 (file)
@@ -349,6 +349,8 @@ enum StatType {
   StatInt_canonicalize_file_name,
   StatInt_confstr,
   StatInt_sched_getaffinity,
+  StatInt_strerror,
+  StatInt_strerror_r,
 
   // Dynamic annotations.
   StatAnnotation,