[compiler-rt] r243595 - [asan, tsan, msan] move the memcmp interceptor from asan/tsan to sanitizer_common. This may potentially lead to more reports from msan as it now sees the reads inside memcmp. To disable, use the flag intercept_memcmp=0. Likewise, it may potentially cause new races to appear due to more strict memcmp checking (flag strict_memcmp=1)
Kostya Serebryany
kcc at google.com
Wed Jul 29 16:53:09 PDT 2015
Author: kcc
Date: Wed Jul 29 18:53:08 2015
New Revision: 243595
URL: http://llvm.org/viewvc/llvm-project?rev=243595&view=rev
Log:
[asan,tsan,msan] move the memcmp interceptor from asan/tsan to sanitizer_common. This may potentially lead to more reports from msan as it now sees the reads inside memcmp. To disable, use the flag intercept_memcmp=0. Likewise, it may potentially cause new races to appear due to more strict memcmp checking (flag strict_memcmp=1)
Added:
compiler-rt/trunk/test/msan/memcmp_test.cc
compiler-rt/trunk/test/tsan/memcmp_race.cc
Modified:
compiler-rt/trunk/lib/asan/asan_flags.inc
compiler-rt/trunk/lib/asan/asan_interceptors.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h
compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
Modified: compiler-rt/trunk/lib/asan/asan_flags.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_flags.inc?rev=243595&r1=243594&r2=243595&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_flags.inc (original)
+++ compiler-rt/trunk/lib/asan/asan_flags.inc Wed Jul 29 18:53:08 2015
@@ -113,9 +113,6 @@ ASAN_FLAG(bool, alloc_dealloc_mismatch,
ASAN_FLAG(bool, new_delete_type_mismatch, true,
"Report errors on mismatch betwen size of new and delete.")
-ASAN_FLAG(bool, strict_memcmp, true,
- "If true, assume that memcmp(p1, p2, n) always reads n bytes before "
- "comparing p1 and p2.")
ASAN_FLAG(
bool, strict_init_order, false,
"If true, assume that dynamic initializers can never access globals from "
Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=243595&r1=243594&r2=243595&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Wed Jul 29 18:53:08 2015
@@ -363,40 +363,6 @@ INTERCEPTOR(void, __cxa_throw, void *a,
}
#endif
-static inline int CharCmp(unsigned char c1, unsigned char c2) {
- return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
-}
-
-INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
- void *ctx;
- ASAN_INTERCEPTOR_ENTER(ctx, memcmp);
- if (UNLIKELY(!asan_inited)) return internal_memcmp(a1, a2, size);
- ENSURE_ASAN_INITED();
- if (flags()->replace_intrin) {
- if (flags()->strict_memcmp) {
- // Check the entire regions even if the first bytes of the buffers are
- // different.
- ASAN_READ_RANGE(ctx, a1, size);
- ASAN_READ_RANGE(ctx, a2, size);
- // Fallthrough to REAL(memcmp) below.
- } else {
- unsigned char c1 = 0, c2 = 0;
- const unsigned char *s1 = (const unsigned char*)a1;
- const unsigned char *s2 = (const unsigned char*)a2;
- uptr i;
- for (i = 0; i < size; i++) {
- c1 = s1[i];
- c2 = s2[i];
- if (c1 != c2) break;
- }
- ASAN_READ_RANGE(ctx, s1, Min(i + 1, size));
- ASAN_READ_RANGE(ctx, s2, Min(i + 1, size));
- return CharCmp(c1, c2);
- }
- }
- return REAL(memcmp(a1, a2, size));
-}
-
// memcpy is called during __asan_init() from the internals of printf(...).
// We do not treat memcpy with to==from as a bug.
// See http://llvm.org/bugs/show_bug.cgi?id=11763.
@@ -767,7 +733,6 @@ void InitializeAsanInterceptors() {
InitializeCommonInterceptors();
// Intercept mem* functions.
- ASAN_INTERCEPT_FUNC(memcmp);
ASAN_INTERCEPT_FUNC(memmove);
ASAN_INTERCEPT_FUNC(memset);
if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
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=243595&r1=243594&r2=243595&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Wed Jul 29 18:53:08 2015
@@ -362,6 +362,42 @@ INTERCEPTOR(char *, strpbrk, const char
#define INIT_STRPBRK
#endif
+#if SANITIZER_INTERCEPT_MEMCMP
+INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
+ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
+ return internal_memcmp(a1, a2, size);
+ if (common_flags()->intercept_memcmp) {
+ if (common_flags()->strict_memcmp) {
+ // Check the entire regions even if the first bytes of the buffers are
+ // different.
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, a1, size);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, a2, size);
+ // Fallthrough to REAL(memcmp) below.
+ } else {
+ unsigned char c1 = 0, c2 = 0;
+ const unsigned char *s1 = (const unsigned char*)a1;
+ const unsigned char *s2 = (const unsigned char*)a2;
+ uptr i;
+ for (i = 0; i < size; i++) {
+ c1 = s1[i];
+ c2 = s2[i];
+ if (c1 != c2) break;
+ }
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
+ return CharCmpX(c1, c2);
+ }
+ }
+ return REAL(memcmp(a1, a2, size));
+}
+
+#define INIT_MEMCMP COMMON_INTERCEPT_FUNCTION(memcmp)
+#else
+#define INIT_MEMCMP
+#endif
+
#if SANITIZER_INTERCEPT_MEMCHR
INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) {
void *ctx;
@@ -5026,6 +5062,7 @@ static void InitializeCommonInterceptors
INIT_STRSPN;
INIT_STRPBRK;
INIT_MEMCHR;
+ INIT_MEMCMP;
INIT_MEMRCHR;
INIT_READ;
INIT_PREAD;
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc?rev=243595&r1=243594&r2=243595&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc Wed Jul 29 18:53:08 2015
@@ -174,6 +174,12 @@ COMMON_FLAG(bool, intercept_strspn, true
COMMON_FLAG(bool, intercept_strpbrk, true,
"If set, uses custom wrappers for strpbrk function "
"to find more errors.")
+COMMON_FLAG(bool, intercept_memcmp, true,
+ "If set, uses custom wrappers for memcmp function "
+ "to find more errors.")
+COMMON_FLAG(bool, strict_memcmp, true,
+ "If true, assume that memcmp(p1, p2, n) always reads n bytes before "
+ "comparing p1 and p2.")
COMMON_FLAG(bool, decorate_proc_maps, false, "If set, decorate sanitizer "
"mappings in /proc/self/maps with "
"user-readable names")
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h?rev=243595&r1=243594&r2=243595&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h Wed Jul 29 18:53:08 2015
@@ -60,6 +60,7 @@
#define SANITIZER_INTERCEPT_STRPBRK 1
#define SANITIZER_INTERCEPT_TEXTDOMAIN SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_STRCASECMP SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_MEMCMP 1
#define SANITIZER_INTERCEPT_MEMCHR 1
#define SANITIZER_INTERCEPT_MEMRCHR SI_FREEBSD || SI_LINUX
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=243595&r1=243594&r2=243595&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Wed Jul 29 18:53:08 2015
@@ -606,20 +606,6 @@ TSAN_INTERCEPTOR(void*, memcpy, void *ds
return internal_memcpy(dst, src, size);
}
-TSAN_INTERCEPTOR(int, memcmp, const void *s1, const void *s2, uptr n) {
- SCOPED_TSAN_INTERCEPTOR(memcmp, s1, s2, n);
- int res = 0;
- uptr len = 0;
- for (; len < n; len++) {
- if ((res = ((const unsigned char *)s1)[len] -
- ((const unsigned char *)s2)[len]))
- break;
- }
- MemoryAccessRange(thr, pc, (uptr)s1, len < n ? len + 1 : n, false);
- MemoryAccessRange(thr, pc, (uptr)s2, len < n ? len + 1 : n, false);
- return res;
-}
-
TSAN_INTERCEPTOR(void*, memmove, void *dst, void *src, uptr n) {
SCOPED_TSAN_INTERCEPTOR(memmove, dst, src, n);
MemoryAccessRange(thr, pc, (uptr)dst, n, true);
@@ -2469,7 +2455,6 @@ void InitializeInterceptors() {
// We need to setup it early, because functions like dlsym() can call it.
REAL(memset) = internal_memset;
REAL(memcpy) = internal_memcpy;
- REAL(memcmp) = internal_memcmp;
// Instruct libc malloc to consume less memory.
#if !SANITIZER_FREEBSD
@@ -2508,7 +2493,6 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(memset);
TSAN_INTERCEPT(memcpy);
TSAN_INTERCEPT(memmove);
- TSAN_INTERCEPT(memcmp);
TSAN_INTERCEPT(strchr);
TSAN_INTERCEPT(strchrnul);
TSAN_INTERCEPT(strrchr);
Added: compiler-rt/trunk/test/msan/memcmp_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/memcmp_test.cc?rev=243595&view=auto
==============================================================================
--- compiler-rt/trunk/test/msan/memcmp_test.cc (added)
+++ compiler-rt/trunk/test/msan/memcmp_test.cc Wed Jul 29 18:53:08 2015
@@ -0,0 +1,15 @@
+// RUN: %clangxx_msan -O0 -g %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s
+// RUN: MSAN_OPTIONS=intercept_memcmp=0 %run %t
+
+#include <string.h>
+int main(int argc, char **argv) {
+ char a1[4];
+ char a2[4];
+ for (int i = 0; i < argc * 3; i++)
+ a2[i] = a1[i] = i;
+ int res = memcmp(a1, a2, 4);
+ return res;
+ // CHECK: Uninitialized bytes in __interceptor_memcmp at offset 3
+ // CHECK: MemorySanitizer: use-of-uninitialized-value
+}
Added: compiler-rt/trunk/test/tsan/memcmp_race.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/memcmp_race.cc?rev=243595&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/memcmp_race.cc (added)
+++ compiler-rt/trunk/test/tsan/memcmp_race.cc Wed Jul 29 18:53:08 2015
@@ -0,0 +1,42 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
+#include "test.h"
+#include <string.h>
+
+char *data0 = new char[10];
+char *data1 = new char[10];
+char *data2 = new char[10];
+
+void *Thread1(void *x) {
+ static volatile int size = 1;
+ static volatile int sink;
+ sink = memcmp(data0+5, data1, size);
+ barrier_wait(&barrier);
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ static volatile int size = 4;
+ barrier_wait(&barrier);
+ memcpy(data0+5, data2, size);
+ return NULL;
+}
+
+int main() {
+ barrier_init(&barrier, 2);
+ fprintf(stderr, "addr=%p\n", &data0[5]);
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, NULL);
+ pthread_create(&t[1], NULL, Thread2, NULL);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+ return 0;
+}
+
+// CHECK: addr=[[ADDR:0x[0-9,a-f]+]]
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: Write of size 1 at [[ADDR]] by thread T2:
+// CHECK: #0 memcpy
+// CHECK: #1 Thread2
+// CHECK: Previous read of size 1 at [[ADDR]] by thread T1:
+// CHECK: #0 memcmp
+// CHECK: #1 Thread1
More information about the llvm-commits
mailing list