[compiler-rt] r304858 - [tsan]: Fix GNU version of strerror_r interceptor

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 6 18:53:39 PDT 2017


Author: vitalybuka
Date: Tue Jun  6 20:53:38 2017
New Revision: 304858

URL: http://llvm.org/viewvc/llvm-project?rev=304858&view=rev
Log:
[tsan]: Fix GNU version of strerror_r interceptor

GNU version of strerror_r returns a result pointer that doesn't match the input
buffer. The result pointer is in fact a pointer to some internal storage.
TSAN was recording a write to this location, which was incorrect.

Fixed https://github.com/google/sanitizers/issues/696

Added:
    compiler-rt/trunk/test/msan/Linux/strerror_r.cc
    compiler-rt/trunk/test/tsan/strerror_r.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc?rev=304858&r1=304857&r2=304858&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Tue Jun  6 20:53:38 2017
@@ -3395,7 +3395,10 @@ INTERCEPTOR(char *, strerror_r, int errn
   // its metadata. See
   // https://github.com/google/sanitizers/issues/321.
   char *res = REAL(strerror_r)(errnum, buf, buflen);
-  COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+  if (res == buf)
+    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
+  else
+    COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
   return res;
 }
 #endif //(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE ||

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc?rev=304858&r1=304857&r2=304858&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc Tue Jun  6 20:53:38 2017
@@ -345,6 +345,7 @@ void MemoryAccessRange(ThreadState *thr,
   StatInc(thr, StatMopRange);
 
   if (*shadow_mem == kShadowRodata) {
+    DCHECK(!is_write);
     // Access to .rodata section, no races here.
     // Measurements show that it can be 10-20% of all memory accesses.
     StatInc(thr, StatMopRangeRodata);

Added: compiler-rt/trunk/test/msan/Linux/strerror_r.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/Linux/strerror_r.cc?rev=304858&view=auto
==============================================================================
--- compiler-rt/trunk/test/msan/Linux/strerror_r.cc (added)
+++ compiler-rt/trunk/test/msan/Linux/strerror_r.cc Tue Jun  6 20:53:38 2017
@@ -0,0 +1,18 @@
+// RUN: %clang_msan -O0 -g %s -o %t && %run %t
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+int main() {
+  char buf[1000];
+  char *res = strerror_r(EINVAL, buf, sizeof(buf));
+  assert(res);
+  volatile int z = strlen(res);
+
+  res = strerror_r(-1, buf, sizeof(buf));
+  assert(res);
+  z = strlen(res);
+
+  return 0;
+}

Added: compiler-rt/trunk/test/tsan/strerror_r.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/strerror_r.cc?rev=304858&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/strerror_r.cc (added)
+++ compiler-rt/trunk/test/tsan/strerror_r.cc Tue Jun  6 20:53:38 2017
@@ -0,0 +1,28 @@
+// RUN: %clangxx_tsan -O1 -DTEST_ERROR=ERANGE %s -o %t && %run %t 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-SYS %s
+// RUN: %clangxx_tsan -O1 -DTEST_ERROR=-1 %s -o %t && not %run %t 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-USER %s
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+
+char buffer[1000];
+
+void *Thread(void *p) {
+  return strerror_r(TEST_ERROR, buffer, sizeof(buffer));
+}
+
+int main() {
+  pthread_t th[2];
+  pthread_create(&th[0], 0, Thread, 0);
+  pthread_create(&th[1], 0, Thread, 0);
+  pthread_join(th[0], 0);
+  pthread_join(th[1], 0);
+  fprintf(stderr, "DONE\n");
+}
+
+// CHECK-USER: WARNING: ThreadSanitizer: data race
+// CHECK-SYS-NOT: WARNING: ThreadSanitizer: data race
+
+// CHECK: DONE




More information about the llvm-commits mailing list