[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 llvm-svn: 304858
This commit is contained in:
parent
7945248267
commit
d9bc851fb3
|
@ -3395,7 +3395,10 @@ INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
|
|||
// 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 ||
|
||||
|
|
|
@ -345,6 +345,7 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
|
|||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue