Index: lib/sanitizer_common/sanitizer_common_interceptors.inc =================================================================== --- lib/sanitizer_common/sanitizer_common_interceptors.inc +++ lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -3395,7 +3395,10 @@ // 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 || Index: lib/tsan/rtl/tsan_rtl_thread.cc =================================================================== --- lib/tsan/rtl/tsan_rtl_thread.cc +++ lib/tsan/rtl/tsan_rtl_thread.cc @@ -345,6 +345,7 @@ 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); Index: test/msan/Linux/strerror_r.c =================================================================== --- /dev/null +++ test/msan/Linux/strerror_r.c @@ -0,0 +1,23 @@ +// RUN: %clang_msan -O0 -g %s -o %t && %run %t + +// UNSUPPORTED: android + +#define _GNU_SOURCE 1 +#include +#include +#include + +int main() { + char buf[1000]; + char* res = strerror_r(EINVAL, buf, sizeof(buf)); + assert(res); + assert(res != buf); + volatile int z = strlen(res); + + res = strerror_r(-1, buf, sizeof(buf)); + assert(res); + assert(res == buf); + z = strlen(res); + + return 0; +} Index: test/tsan/strerror_r.cc =================================================================== --- /dev/null +++ test/tsan/strerror_r.cc @@ -0,0 +1,37 @@ +// 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 + +// UNSUPPORTED: android + +#define _GNU_SOURCE 1 + +#include "test.h" + +#include +#include +#include +#include + +char buffer[1000]; + +void *Thread(void *p) { + barrier_wait(&barrier); + char* error = strerror_r(TEST_ERROR, buffer, sizeof(buffer)); + assert(TEST_ERROR == -1 || error != buffer); + return 0; +} + +int main() { + barrier_init(&barrier, 2); + 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