Skip to content

Commit 4052de6

Browse files
[tsan] Fix calculation of shadow end address in MemoryAccessRangeT (#98404)
MemoryAccessRangeT overestimates the size of the shadow region by 8x, occasionally leading to assertion failure: ``` RawShadow* shadow_mem = MemToShadow(addr); ... // Check that end of shadow is valid if (!IsShadowMem(shadow_mem + size * kShadowCnt - 1)) { DCHECK(IsShadowMem(shadow_mem + size * kShadowCnt - 1)); ``` It is erroneous for two separate reasons: - it uses kShadowCnt (== 4) instead of kShadowMultiplier (== 2) - since shadow_mem is a RawShadow*, pointer arithmetic is multiplied by sizeof(RawShadow) == 4 This patch fixes the calculation, and also improves the debugging information. The assertion error was observed on a buildbot (https://lab.llvm.org/staging/#/builders/89/builds/656/steps/13/logs/stdio): ``` Bad shadow addr 0x3000000190bc (7fffffffe85f) ThreadSanitizer: CHECK failed: tsan_rtl_access.cpp:690 "((IsShadowMem(shadow_mem + size * kShadowCnt - 1))) != (0)" (0x0, 0x0) (tid=2202676) ``` Notice that 0x3000000190bc is not the correct shadow for the end address 0x7fffffffe85f. This error is more commonly observed on high-entropy ASLR systems, since ASLR may be disabled (if the randomized memory layout is incompatible), leading to an allocation near the boundaries of the high app memory region (and therefore a shadow end that may be erroneously calculated to be past the end of the shadow region). Also note that the assertion is guarded by SANITIZER_DEBUG. --------- Co-authored-by: Vitaly Buka <[email protected]>
1 parent a31cbd2 commit 4052de6

File tree

1 file changed

+14
-8
lines changed

1 file changed

+14
-8
lines changed

compiler-rt/lib/tsan/rtl/tsan_rtl_access.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -672,22 +672,28 @@ void MemoryAccessRangeT(ThreadState* thr, uptr pc, uptr addr, uptr size) {
672672

673673
#if SANITIZER_DEBUG
674674
if (!IsAppMem(addr)) {
675-
Printf("Access to non app mem %zx\n", addr);
675+
Printf("Access to non app mem start: %p\n", (void*)addr);
676676
DCHECK(IsAppMem(addr));
677677
}
678678
if (!IsAppMem(addr + size - 1)) {
679-
Printf("Access to non app mem %zx\n", addr + size - 1);
679+
Printf("Access to non app mem end: %p\n", (void*)(addr + size - 1));
680680
DCHECK(IsAppMem(addr + size - 1));
681681
}
682682
if (!IsShadowMem(shadow_mem)) {
683-
Printf("Bad shadow addr %p (%zx)\n", static_cast<void*>(shadow_mem), addr);
683+
Printf("Bad shadow start addr: %p (%p)\n", shadow_mem, (void*)addr);
684684
DCHECK(IsShadowMem(shadow_mem));
685685
}
686-
if (!IsShadowMem(shadow_mem + size * kShadowCnt - 1)) {
687-
Printf("Bad shadow addr %p (%zx)\n",
688-
static_cast<void*>(shadow_mem + size * kShadowCnt - 1),
689-
addr + size - 1);
690-
DCHECK(IsShadowMem(shadow_mem + size * kShadowCnt - 1));
686+
687+
RawShadow* shadow_mem_end = reinterpret_cast<RawShadow*>(
688+
reinterpret_cast<uptr>(shadow_mem) + size * kShadowMultiplier - 1);
689+
if (!IsShadowMem(shadow_mem_end)) {
690+
Printf("Bad shadow end addr: %p (%p)\n", shadow_mem_end,
691+
(void*)(addr + size - 1));
692+
Printf(
693+
"Shadow start addr (ok): %p (%p); size: 0x%zx; kShadowMultiplier: "
694+
"%zx\n",
695+
shadow_mem, (void*)addr, size, kShadowMultiplier);
696+
DCHECK(IsShadowMem(shadow_mem_end));
691697
}
692698
#endif
693699

0 commit comments

Comments
 (0)