[compiler-rt] [compiler-rt] [Darwin] Strip MTE tags from ASAN and TSAN (PR #166453)

Andrew Haberlandt via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 5 12:04:11 PST 2025


https://github.com/ndrewh updated https://github.com/llvm/llvm-project/pull/166453

>From 8a69c6034444ab8e0b9d3d1a9db1de0d28ce8bff Mon Sep 17 00:00:00 2001
From: Andrew Haberlandt <ahaberlandt at apple.com>
Date: Tue, 4 Nov 2025 13:59:03 -0800
Subject: [PATCH 1/2] [compiler-rt] Strip MTE tags from ASAN and TSAN

ASAN and TSAN need to strip tags in order to compute the correct shadow
addresses.
---
 compiler-rt/lib/asan/asan_mapping.h      | 11 ++++++++++-
 compiler-rt/lib/tsan/rtl/tsan_platform.h | 17 ++++++++++++++---
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h
index bddae9a074056..9fa7f9014445c 100644
--- a/compiler-rt/lib/asan/asan_mapping.h
+++ b/compiler-rt/lib/asan/asan_mapping.h
@@ -281,11 +281,18 @@ extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;  // Initialized in __asan_init.
 
 }  // namespace __asan
 
+#  if SANITIZER_APPLE && SANITIZER_WORDSIZE == 64
+#    define TAG_MASK ((uptr)0x0f << 56)  // Lower half of top byte
+#    define STRIP_TAG(addr) ((addr) & ~TAG_MASK)
+#  else
+#    define STRIP_TAG(addr) (addr)
+#  endif
+
 #  if defined(__sparc__) && SANITIZER_WORDSIZE == 64
 #    include "asan_mapping_sparc64.h"
 #  else
 #    define MEM_TO_SHADOW(mem) \
-      (((mem) >> ASAN_SHADOW_SCALE) + (ASAN_SHADOW_OFFSET))
+      ((STRIP_TAG(mem) >> ASAN_SHADOW_SCALE) + (ASAN_SHADOW_OFFSET))
 #    define SHADOW_TO_MEM(mem) \
       (((mem) - (ASAN_SHADOW_OFFSET)) << (ASAN_SHADOW_SCALE))
 
@@ -377,6 +384,7 @@ static inline uptr MemToShadowSize(uptr size) {
 
 static inline bool AddrIsInMem(uptr a) {
   PROFILE_ASAN_MAPPING();
+  a = STRIP_TAG(a);
   return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a) ||
          (flags()->protect_shadow_gap == 0 && AddrIsInShadowGap(a));
 }
@@ -389,6 +397,7 @@ static inline uptr MemToShadow(uptr p) {
 
 static inline bool AddrIsInShadow(uptr a) {
   PROFILE_ASAN_MAPPING();
+  a = STRIP_TAG(a);
   return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a);
 }
 
diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h
index 00b493bf2d931..ac48392088fb3 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_platform.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h
@@ -947,6 +947,16 @@ uptr MetaShadowBeg(void) { return SelectMapping<MappingField>(kMetaShadowBeg); }
 ALWAYS_INLINE
 uptr MetaShadowEnd(void) { return SelectMapping<MappingField>(kMetaShadowEnd); }
 
+ALWAYS_INLINE
+uptr StripTag(uptr addr) {
+#if SANITIZER_APPLE
+  constexpr uptr kTagMask = ((uptr)0x0f << 56);  // Lower half of top byte
+  return addr & ~kTagMask;
+#else
+  return addr;
+#endif
+}
+
 struct IsAppMemImpl {
   template <typename Mapping>
   static bool Apply(uptr mem) {
@@ -958,7 +968,7 @@ struct IsAppMemImpl {
 };
 
 ALWAYS_INLINE
-bool IsAppMem(uptr mem) { return SelectMapping<IsAppMemImpl>(mem); }
+bool IsAppMem(uptr mem) { return SelectMapping<IsAppMemImpl>(StripTag(mem)); }
 
 struct IsShadowMemImpl {
   template <typename Mapping>
@@ -997,7 +1007,8 @@ struct MemToShadowImpl {
 
 ALWAYS_INLINE
 RawShadow *MemToShadow(uptr x) {
-  return reinterpret_cast<RawShadow *>(SelectMapping<MemToShadowImpl>(x));
+  return reinterpret_cast<RawShadow*>(
+      SelectMapping<MemToShadowImpl>(StripTag(x)));
 }
 
 struct MemToMetaImpl {
@@ -1011,7 +1022,7 @@ struct MemToMetaImpl {
 };
 
 ALWAYS_INLINE
-u32 *MemToMeta(uptr x) { return SelectMapping<MemToMetaImpl>(x); }
+u32* MemToMeta(uptr x) { return SelectMapping<MemToMetaImpl>(StripTag(x)); }
 
 struct ShadowToMemImpl {
   template <typename Mapping>

>From 09d783ec331b15a1d978e361c26a2afbbe4d645c Mon Sep 17 00:00:00 2001
From: Andrew Haberlandt <ahaberlandt at apple.com>
Date: Wed, 5 Nov 2025 12:03:11 -0800
Subject: [PATCH 2/2] STRIP_TAG => STRIP_MTE_TAG, move to common

---
 compiler-rt/lib/asan/asan_mapping.h           | 13 +++---------
 .../lib/sanitizer_common/sanitizer_platform.h |  7 +++++++
 compiler-rt/lib/tsan/rtl/tsan_platform.h      | 20 +++++++------------
 3 files changed, 17 insertions(+), 23 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h
index 9fa7f9014445c..338324686a31d 100644
--- a/compiler-rt/lib/asan/asan_mapping.h
+++ b/compiler-rt/lib/asan/asan_mapping.h
@@ -281,18 +281,11 @@ extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd;  // Initialized in __asan_init.
 
 }  // namespace __asan
 
-#  if SANITIZER_APPLE && SANITIZER_WORDSIZE == 64
-#    define TAG_MASK ((uptr)0x0f << 56)  // Lower half of top byte
-#    define STRIP_TAG(addr) ((addr) & ~TAG_MASK)
-#  else
-#    define STRIP_TAG(addr) (addr)
-#  endif
-
 #  if defined(__sparc__) && SANITIZER_WORDSIZE == 64
 #    include "asan_mapping_sparc64.h"
 #  else
 #    define MEM_TO_SHADOW(mem) \
-      ((STRIP_TAG(mem) >> ASAN_SHADOW_SCALE) + (ASAN_SHADOW_OFFSET))
+      ((STRIP_MTE_TAG(mem) >> ASAN_SHADOW_SCALE) + (ASAN_SHADOW_OFFSET))
 #    define SHADOW_TO_MEM(mem) \
       (((mem) - (ASAN_SHADOW_OFFSET)) << (ASAN_SHADOW_SCALE))
 
@@ -384,7 +377,7 @@ static inline uptr MemToShadowSize(uptr size) {
 
 static inline bool AddrIsInMem(uptr a) {
   PROFILE_ASAN_MAPPING();
-  a = STRIP_TAG(a);
+  a = STRIP_MTE_TAG(a);
   return AddrIsInLowMem(a) || AddrIsInMidMem(a) || AddrIsInHighMem(a) ||
          (flags()->protect_shadow_gap == 0 && AddrIsInShadowGap(a));
 }
@@ -397,7 +390,7 @@ static inline uptr MemToShadow(uptr p) {
 
 static inline bool AddrIsInShadow(uptr a) {
   PROFILE_ASAN_MAPPING();
-  a = STRIP_TAG(a);
+  a = STRIP_MTE_TAG(a);
   return AddrIsInLowShadow(a) || AddrIsInMidShadow(a) || AddrIsInHighShadow(a);
 }
 
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
index 13099fe84b0aa..1b47f3e24d12d 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
@@ -497,4 +497,11 @@
 #  endif
 #endif
 
+#if SANITIZER_APPLE && SANITIZER_WORDSIZE == 64
+// MTE uses the lower half of the top byte.
+#  define STRIP_MTE_TAG(addr) ((addr) & ~((uptr)0x0f << 56))
+#else
+#  define STRIP_MTE_TAG(addr) (addr)
+#endif
+
 #endif  // SANITIZER_PLATFORM_H
diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h
index ac48392088fb3..7089be4d5d7f7 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_platform.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h
@@ -947,16 +947,6 @@ uptr MetaShadowBeg(void) { return SelectMapping<MappingField>(kMetaShadowBeg); }
 ALWAYS_INLINE
 uptr MetaShadowEnd(void) { return SelectMapping<MappingField>(kMetaShadowEnd); }
 
-ALWAYS_INLINE
-uptr StripTag(uptr addr) {
-#if SANITIZER_APPLE
-  constexpr uptr kTagMask = ((uptr)0x0f << 56);  // Lower half of top byte
-  return addr & ~kTagMask;
-#else
-  return addr;
-#endif
-}
-
 struct IsAppMemImpl {
   template <typename Mapping>
   static bool Apply(uptr mem) {
@@ -968,7 +958,9 @@ struct IsAppMemImpl {
 };
 
 ALWAYS_INLINE
-bool IsAppMem(uptr mem) { return SelectMapping<IsAppMemImpl>(StripTag(mem)); }
+bool IsAppMem(uptr mem) {
+  return SelectMapping<IsAppMemImpl>(STRIP_MTE_TAG(mem));
+}
 
 struct IsShadowMemImpl {
   template <typename Mapping>
@@ -1008,7 +1000,7 @@ struct MemToShadowImpl {
 ALWAYS_INLINE
 RawShadow *MemToShadow(uptr x) {
   return reinterpret_cast<RawShadow*>(
-      SelectMapping<MemToShadowImpl>(StripTag(x)));
+      SelectMapping<MemToShadowImpl>(STRIP_MTE_TAG(x)));
 }
 
 struct MemToMetaImpl {
@@ -1022,7 +1014,9 @@ struct MemToMetaImpl {
 };
 
 ALWAYS_INLINE
-u32* MemToMeta(uptr x) { return SelectMapping<MemToMetaImpl>(StripTag(x)); }
+u32* MemToMeta(uptr x) {
+  return SelectMapping<MemToMetaImpl>(STRIP_MTE_TAG(x));
+}
 
 struct ShadowToMemImpl {
   template <typename Mapping>



More information about the llvm-commits mailing list