Index: compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp =================================================================== --- compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -769,6 +769,11 @@ if (!fix_mmap_addr(&addr, sz, flags)) return MAP_FAILED; void *res = real_mmap(addr, sz, prot, flags, fd, off); if (res != MAP_FAILED) { + if (!IsAppMem((uptr)res) || !IsAppMem((uptr)res + sz - 1)) { + Report("ThreadSanitizer: mmap at bad address: addr=%p size=%p res=%p\n", + addr, (void*)sz, res); + Die(); + } if (fd > 0) FdAccess(thr, pc, fd); MemoryRangeImitateWriteOrResetRange(thr, pc, (uptr)res, sz); } Index: compiler-rt/lib/tsan/rtl/tsan_rtl.cpp =================================================================== --- compiler-rt/lib/tsan/rtl/tsan_rtl.cpp +++ compiler-rt/lib/tsan/rtl/tsan_rtl.cpp @@ -77,12 +77,19 @@ new((void*)hdr) Trace(); // We are going to use only a small part of the trace with the default // value of history_size. However, the constructor writes to the whole trace. - // Unmap the unused part. + // Release the unused part. uptr hdr_end = hdr + sizeof(Trace); hdr_end -= sizeof(TraceHeader) * (kTraceParts - TraceParts()); hdr_end = RoundUp(hdr_end, GetPageSizeCached()); - if (hdr_end < hdr + sizeof(Trace)) - UnmapOrDie((void*)hdr_end, hdr + sizeof(Trace) - hdr_end); + if (hdr_end < hdr + sizeof(Trace)) { + ReleaseMemoryPagesToOS(hdr_end, hdr + sizeof(Trace)); + uptr unused = hdr + sizeof(Trace) - hdr_end; + if (hdr_end != (uptr)MmapFixedNoAccess(hdr_end, unused)) { + Report("ThreadSanitizer: failed to mprotect(%p, %p)\n", + hdr_end, unused); + CHECK("unable to mprotect" && 0); + } + } void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext)); return new(mem) ThreadContext(tid); } Index: compiler-rt/test/tsan/mmap_lots.cpp =================================================================== --- /dev/null +++ compiler-rt/test/tsan/mmap_lots.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s + +// Test that mmap does not return unexpected addresses +// (the check is in the interceptor). + +#include +#include +#include +#include +#include +#include +#include +#include + +int main() { + int fd = open("/dev/zero", O_RDWR); + if (fd == -1) perror("open(/dev/zero)"), exit(1); + for (size_t mmap_size = 64ull << 30; mmap_size >= 4 << 10; mmap_size /= 2) { + size_t allocated = 0; + while (mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, + fd, 0) != MAP_FAILED) { + allocated += mmap_size; + } + fprintf(stderr, "allocated %zu with size %zu\n", allocated, mmap_size); + } + fprintf(stderr, "DONE\n"); +} + +// CHECK: DONE