diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -445,8 +445,10 @@ c2 = (unsigned char)s2[i]; if (c1 != c2 || c1 == '\0') break; } - COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1); - COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1); + if (common_flags()->intercept_strcmp) { + COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1); + COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1); + } int result = CharCmpX(c1, c2); CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1, s2, result); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc @@ -195,6 +195,9 @@ COMMON_FLAG(bool, intercept_strpbrk, true, "If set, uses custom wrappers for strpbrk function " "to find more errors.") +COMMON_FLAG( + bool, intercept_strcmp, true, + "If set, uses custom wrappers for strcmp functions to find more errors.") COMMON_FLAG(bool, intercept_strlen, true, "If set, uses custom wrappers for strlen and strnlen functions " "to find more errors.") diff --git a/compiler-rt/test/asan/TestCases/strcmp.c b/compiler-rt/test/asan/TestCases/strcmp.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/strcmp.c @@ -0,0 +1,19 @@ +// RUN: %clang_asan %s -o %t +// RUN: %env_asan_opts=intercept_strcmp=false %run %t 2>&1 +// RUN: %env_asan_opts=intercept_strcmp=true not %run %t 2>&1 | FileCheck %s +// RUN: not %run %t 2>&1 | FileCheck %s + +#include +#include +#include + +int main(int argc, char **argv) { + char s1[] = "abcd"; + char s2[] = "1234"; + assert(strcmp(s1, s2) > 0); + assert(strcmp(s1 - 1, s2)); + + // CHECK: {{.*ERROR: AddressSanitizer: stack-buffer-underflow on address}} + // CHECK: READ of size 1 + return 0; +} diff --git a/compiler-rt/test/msan/strcmp.c b/compiler-rt/test/msan/strcmp.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/msan/strcmp.c @@ -0,0 +1,20 @@ +// RUN: %clang_msan %s -o %t +// RUN: MSAN_OPTIONS=intercept_strcmp=false %run %t 2>&1 +// RUN: MSAN_OPTIONS=intercept_strcmp=true not %run %t 2>&1 | FileCheck %s +// RUN: not %run %t 2>&1 | FileCheck %s + +#include +#include +#include + +int main(int argc, char **argv) { + char undef; + char s1[] = "abcd"; + char s2[] = "1234"; + assert(strcmp(s1, s2) > 0); + s2[0] = undef; + assert(strcmp(s1, s2)); + + // CHECK: {{.*WARNING: MemorySanitizer: use-of-uninitialized-value}} + return 0; +}