Index: compiler-rt/lib/lsan/lsan_common.h =================================================================== --- compiler-rt/lib/lsan/lsan_common.h +++ compiler-rt/lib/lsan/lsan_common.h @@ -145,6 +145,8 @@ struct CheckForLeaksParam { Frontier frontier; LeakedChunks leaks; + tid_t caller_tid; + uptr caller_sp; bool success = false; }; Index: compiler-rt/lib/lsan/lsan_common.cpp =================================================================== --- compiler-rt/lib/lsan/lsan_common.cpp +++ compiler-rt/lib/lsan/lsan_common.cpp @@ -365,7 +365,8 @@ // Scans thread data (stacks and TLS) for heap pointers. static void ProcessThreads(SuspendedThreadsList const &suspended_threads, - Frontier *frontier) { + Frontier *frontier, tid_t caller_tid, + uptr caller_sp) { InternalMmapVector registers; for (uptr i = 0; i < suspended_threads.ThreadCount(); i++) { tid_t os_id = static_cast(suspended_threads.GetThreadID(i)); @@ -392,6 +393,9 @@ continue; sp = stack_begin; } + if (suspended_threads.GetThreadID(i) == caller_tid) { + sp = caller_sp; + } if (flags()->use_registers && have_registers) { uptr registers_begin = reinterpret_cast(registers.data()); @@ -572,7 +576,8 @@ // Sets the appropriate tag on each chunk. static void ClassifyAllChunks(SuspendedThreadsList const &suspended_threads, - Frontier *frontier) { + Frontier *frontier, tid_t caller_tid, + uptr caller_sp) { const InternalMmapVector &suppressed_stacks = GetSuppressionContext()->GetSortedSuppressedStacks(); if (!suppressed_stacks.empty()) { @@ -581,7 +586,7 @@ } ForEachChunk(CollectIgnoredCb, frontier); ProcessGlobalRegions(frontier); - ProcessThreads(suspended_threads, frontier); + ProcessThreads(suspended_threads, frontier, caller_tid, caller_sp); ProcessRootRegions(frontier); FloodFillTag(frontier, kReachable); @@ -677,7 +682,8 @@ CHECK(param); CHECK(!param->success); ReportUnsuspendedThreads(suspended_threads); - ClassifyAllChunks(suspended_threads, ¶m->frontier); + ClassifyAllChunks(suspended_threads, ¶m->frontier, param->caller_tid, + param->caller_sp); ForEachChunk(CollectLeaksCb, ¶m->leaks); // Clean up for subsequent leak checks. This assumes we did not overwrite any // kIgnored tags. @@ -716,6 +722,12 @@ for (int i = 0;; ++i) { EnsureMainThreadIDIsCorrect(); CheckForLeaksParam param; + // Capture calling thread's stack pointer early, to avoid false negatives. + // Old frame with dead pointers might be overlapped by new frame inside + // CheckForLeaks which does not use bytes with pointers before the + // threads are suspended and stack pointers captured. + param.caller_tid = GetTid(); + param.caller_sp = reinterpret_cast(__builtin_frame_address(0)); LockStuffAndStopTheWorld(CheckForLeaksCallback, ¶m); if (!param.success) { Report("LeakSanitizer has encountered a fatal error.\n");