diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2013-10-25 09:45:44 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2013-10-25 09:45:44 +0000 |
commit | 175599be65a5c08551bbe0359a7ca1aadb23ec8b (patch) | |
tree | e5c8ae18a55224a50ffc34163d37116184986d00 | |
parent | aff25aa02098a510eff6eda1a3ec823e5b1fe1aa (diff) | |
download | compiler-rt-175599be65a5c08551bbe0359a7ca1aadb23ec8b.tar.gz compiler-rt-175599be65a5c08551bbe0359a7ca1aadb23ec8b.tar.bz2 compiler-rt-175599be65a5c08551bbe0359a7ca1aadb23ec8b.tar.xz |
tsan: do not crash when apparently bogus fd is passed to e.g. close
some tests test libc/filesystem error handling paths (e.g. close(INT_MAX)),
currently such tests fail
with this change they work as expected
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@193400 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/tsan/rtl/tsan_fd.cc | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/lib/tsan/rtl/tsan_fd.cc b/lib/tsan/rtl/tsan_fd.cc index 703a487a..86db119f 100644 --- a/lib/tsan/rtl/tsan_fd.cc +++ b/lib/tsan/rtl/tsan_fd.cc @@ -42,6 +42,11 @@ struct FdContext { static FdContext fdctx; +static bool bogusfd(int fd) { + // Apparently a bogus fd value. + return fd < 0 || fd >= (1 << 30); +} + static FdSync *allocsync() { FdSync *s = (FdSync*)internal_alloc(MBlockFD, sizeof(FdSync)); atomic_store(&s->rc, 1, memory_order_relaxed); @@ -69,6 +74,7 @@ static void unref(ThreadState *thr, uptr pc, FdSync *s) { } static FdDesc *fddesc(ThreadState *thr, uptr pc, int fd) { + CHECK_GE(fd, 0); CHECK_LT(fd, kTableSize); atomic_uintptr_t *pl1 = &fdctx.tab[fd / kTableSizeL2]; uptr l1 = atomic_load(pl1, memory_order_consume); @@ -148,6 +154,8 @@ bool FdLocation(uptr addr, int *fd, int *tid, u32 *stack) { } void FdAcquire(ThreadState *thr, uptr pc, int fd) { + if (bogusfd(fd)) + return; FdDesc *d = fddesc(thr, pc, fd); FdSync *s = d->sync; DPrintf("#%d: FdAcquire(%d) -> %p\n", thr->tid, fd, s); @@ -157,6 +165,8 @@ void FdAcquire(ThreadState *thr, uptr pc, int fd) { } void FdRelease(ThreadState *thr, uptr pc, int fd) { + if (bogusfd(fd)) + return; FdDesc *d = fddesc(thr, pc, fd); FdSync *s = d->sync; DPrintf("#%d: FdRelease(%d) -> %p\n", thr->tid, fd, s); @@ -166,15 +176,17 @@ void FdRelease(ThreadState *thr, uptr pc, int fd) { } void FdAccess(ThreadState *thr, uptr pc, int fd) { - if (fd < 0) - return; DPrintf("#%d: FdAccess(%d)\n", thr->tid, fd); + if (bogusfd(fd)) + return; FdDesc *d = fddesc(thr, pc, fd); MemoryRead(thr, pc, (uptr)d, kSizeLog8); } void FdClose(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdClose(%d)\n", thr->tid, fd); + if (bogusfd(fd)) + return; FdDesc *d = fddesc(thr, pc, fd); // To catch races between fd usage and close. MemoryWrite(thr, pc, (uptr)d, kSizeLog8); @@ -189,11 +201,15 @@ void FdClose(ThreadState *thr, uptr pc, int fd) { void FdFileCreate(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdFileCreate(%d)\n", thr->tid, fd); + if (bogusfd(fd)) + return; init(thr, pc, fd, &fdctx.filesync); } void FdDup(ThreadState *thr, uptr pc, int oldfd, int newfd) { DPrintf("#%d: FdDup(%d, %d)\n", thr->tid, oldfd, newfd); + if (bogusfd(oldfd) || bogusfd(newfd)) + return; // Ignore the case when user dups not yet connected socket. FdDesc *od = fddesc(thr, pc, oldfd); MemoryRead(thr, pc, (uptr)od, kSizeLog8); @@ -211,32 +227,44 @@ void FdPipeCreate(ThreadState *thr, uptr pc, int rfd, int wfd) { void FdEventCreate(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdEventCreate(%d)\n", thr->tid, fd); + if (bogusfd(fd)) + return; init(thr, pc, fd, allocsync()); } void FdSignalCreate(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdSignalCreate(%d)\n", thr->tid, fd); + if (bogusfd(fd)) + return; init(thr, pc, fd, 0); } void FdInotifyCreate(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdInotifyCreate(%d)\n", thr->tid, fd); + if (bogusfd(fd)) + return; init(thr, pc, fd, 0); } void FdPollCreate(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdPollCreate(%d)\n", thr->tid, fd); + if (bogusfd(fd)) + return; init(thr, pc, fd, allocsync()); } void FdSocketCreate(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdSocketCreate(%d)\n", thr->tid, fd); + if (bogusfd(fd)) + return; // It can be a UDP socket. init(thr, pc, fd, &fdctx.socksync); } void FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd) { DPrintf("#%d: FdSocketAccept(%d, %d)\n", thr->tid, fd, newfd); + if (bogusfd(fd)) + return; // Synchronize connect->accept. Acquire(thr, pc, (uptr)&fdctx.connectsync); init(thr, pc, newfd, &fdctx.socksync); @@ -244,12 +272,16 @@ void FdSocketAccept(ThreadState *thr, uptr pc, int fd, int newfd) { void FdSocketConnecting(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdSocketConnecting(%d)\n", thr->tid, fd); + if (bogusfd(fd)) + return; // Synchronize connect->accept. Release(thr, pc, (uptr)&fdctx.connectsync); } void FdSocketConnect(ThreadState *thr, uptr pc, int fd) { DPrintf("#%d: FdSocketConnect(%d)\n", thr->tid, fd); + if (bogusfd(fd)) + return; init(thr, pc, fd, &fdctx.socksync); } |