[compiler-rt] [scudo] [MTE] resize stack depot for allocation ring buffer (PR #74515)

Florian Mayer via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 25 12:08:58 PST 2024


https://github.com/fmayer updated https://github.com/llvm/llvm-project/pull/74515

>From 267365a96f1beb64c28928565958058beb838036 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Fri, 1 Dec 2023 16:46:29 -0800
Subject: [PATCH 01/16] [scudo] resize stack depot for allocation ring buffer

---
 compiler-rt/lib/scudo/standalone/combined.h   | 101 +++++++++++----
 .../standalone/fuzz/get_error_info_fuzzer.cpp |  14 +--
 compiler-rt/lib/scudo/standalone/platform.h   |  10 --
 .../lib/scudo/standalone/stack_depot.h        | 118 +++++++++++++-----
 .../scudo/standalone/wrappers_c_bionic.cpp    |   9 +-
 5 files changed, 173 insertions(+), 79 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index 4624f83d142a0de..49cdc44cd80d266 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -290,7 +290,9 @@ class Allocator {
     uptr Size =
         android_unsafe_frame_pointer_chase(Stack, MaxTraceSize + DiscardFrames);
     Size = Min<uptr>(Size, MaxTraceSize + DiscardFrames);
-    return Depot.insert(Stack + Min<uptr>(DiscardFrames, Size), Stack + Size);
+    return reinterpret_cast<StackDepot *>(RawStackDepot)
+        ->insert(RawStackDepot, Stack + Min<uptr>(DiscardFrames, Size),
+                 Stack + Size);
 #else
     return 0;
 #endif
@@ -917,8 +919,14 @@ class Allocator {
       Primary.Options.clear(OptionBit::AddLargeAllocationSlack);
   }
 
-  const char *getStackDepotAddress() const {
-    return reinterpret_cast<const char *>(&Depot);
+  const char *getStackDepotAddress() {
+    initThreadMaybe();
+    return RawStackDepot;
+  }
+
+  uptr getStackDepotSize() {
+    initThreadMaybe();
+    return StackDepotSize;
   }
 
   const char *getRegionInfoArrayAddress() const {
@@ -941,45 +949,54 @@ class Allocator {
 
   static const uptr MaxTraceSize = 64;
 
-  static void collectTraceMaybe(const StackDepot *Depot,
+  static void collectTraceMaybe(const char *RawStackDepot,
                                 uintptr_t (&Trace)[MaxTraceSize], u32 Hash) {
+    auto *Depot = reinterpret_cast<const StackDepot *>(RawStackDepot);
     uptr RingPos, Size;
-    if (!Depot->find(Hash, &RingPos, &Size))
+    if (!Depot->find(RawStackDepot, Hash, &RingPos, &Size))
       return;
     for (unsigned I = 0; I != Size && I != MaxTraceSize; ++I)
-      Trace[I] = static_cast<uintptr_t>((*Depot)[RingPos + I]);
+      Trace[I] = static_cast<uintptr_t>(Depot->at(RawStackDepot, RingPos + I));
   }
 
   static void getErrorInfo(struct scudo_error_info *ErrorInfo,
                            uintptr_t FaultAddr, const char *DepotPtr,
-                           const char *RegionInfoPtr, const char *RingBufferPtr,
-                           size_t RingBufferSize, const char *Memory,
-                           const char *MemoryTags, uintptr_t MemoryAddr,
-                           size_t MemorySize) {
+                           size_t DepotSize, const char *RegionInfoPtr,
+                           const char *RingBufferPtr, size_t RingBufferSize,
+                           const char *Memory, const char *MemoryTags,
+                           uintptr_t MemoryAddr, size_t MemorySize) {
     *ErrorInfo = {};
     if (!allocatorSupportsMemoryTagging<Config>() ||
         MemoryAddr + MemorySize < MemoryAddr)
       return;
 
-    auto *Depot = reinterpret_cast<const StackDepot *>(DepotPtr);
+    if (DepotPtr && DepotSize < sizeof(StackDepot)) {
+      return;
+    }
+    if (DepotPtr &&
+        !reinterpret_cast<const StackDepot *>(DepotPtr)->isValid(DepotSize)) {
+      // corrupted stack depot.
+      return;
+    }
+
     size_t NextErrorReport = 0;
 
     // Check for OOB in the current block and the two surrounding blocks. Beyond
     // that, UAF is more likely.
     if (extractTag(FaultAddr) != 0)
-      getInlineErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, Depot,
+      getInlineErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, DepotPtr,
                          RegionInfoPtr, Memory, MemoryTags, MemoryAddr,
                          MemorySize, 0, 2);
 
     // Check the ring buffer. For primary allocations this will only find UAF;
     // for secondary allocations we can find either UAF or OOB.
-    getRingBufferErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, Depot,
+    getRingBufferErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, DepotPtr,
                            RingBufferPtr, RingBufferSize);
 
     // Check for OOB in the 28 blocks surrounding the 3 we checked earlier.
     // Beyond that we are likely to hit false positives.
     if (extractTag(FaultAddr) != 0)
-      getInlineErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, Depot,
+      getInlineErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, DepotPtr,
                          RegionInfoPtr, Memory, MemoryTags, MemoryAddr,
                          MemorySize, 2, 16);
   }
@@ -1027,7 +1044,9 @@ class Allocator {
   uptr GuardedAllocSlotSize = 0;
 #endif // GWP_ASAN_HOOKS
 
-  StackDepot Depot;
+  char *RawStackDepot = nullptr;
+  uptr StackDepotSize = 0;
+  MemMapT RawStackDepotMap;
 
   struct AllocationRingBuffer {
     struct Entry {
@@ -1243,7 +1262,8 @@ class Allocator {
   }
 
   void storePrimaryAllocationStackMaybe(const Options &Options, void *Ptr) {
-    if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)))
+    if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)) ||
+        !RawRingBuffer)
       return;
     auto *Ptr32 = reinterpret_cast<u32 *>(Ptr);
     Ptr32[MemTagAllocationTraceIndex] = collectStackTrace();
@@ -1276,7 +1296,8 @@ class Allocator {
 
   void storeSecondaryAllocationStackMaybe(const Options &Options, void *Ptr,
                                           uptr Size) {
-    if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)))
+    if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)) ||
+        !RawRingBuffer)
       return;
 
     u32 Trace = collectStackTrace();
@@ -1291,7 +1312,8 @@ class Allocator {
 
   void storeDeallocationStackMaybe(const Options &Options, void *Ptr,
                                    u8 PrevTag, uptr Size) {
-    if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)))
+    if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)) ||
+        !RawRingBuffer)
       return;
 
     auto *Ptr32 = reinterpret_cast<u32 *>(Ptr);
@@ -1312,7 +1334,7 @@ class Allocator {
 
   static void getInlineErrorInfo(struct scudo_error_info *ErrorInfo,
                                  size_t &NextErrorReport, uintptr_t FaultAddr,
-                                 const StackDepot *Depot,
+                                 const char *RawStackDepot,
                                  const char *RegionInfoPtr, const char *Memory,
                                  const char *MemoryTags, uintptr_t MemoryAddr,
                                  size_t MemorySize, size_t MinDistance,
@@ -1377,8 +1399,10 @@ class Allocator {
           UntaggedFaultAddr < ChunkAddr ? BUFFER_UNDERFLOW : BUFFER_OVERFLOW;
       R->allocation_address = ChunkAddr;
       R->allocation_size = Header.SizeOrUnusedBytes;
-      collectTraceMaybe(Depot, R->allocation_trace,
-                        Data[MemTagAllocationTraceIndex]);
+      if (RawStackDepot) {
+        collectTraceMaybe(RawStackDepot, R->allocation_trace,
+                          Data[MemTagAllocationTraceIndex]);
+      }
       R->allocation_tid = Data[MemTagAllocationTidIndex];
       return NextErrorReport == NumErrorReports;
     };
@@ -1395,13 +1419,13 @@ class Allocator {
   static void getRingBufferErrorInfo(struct scudo_error_info *ErrorInfo,
                                      size_t &NextErrorReport,
                                      uintptr_t FaultAddr,
-                                     const StackDepot *Depot,
+                                     const char *RawStackDepot,
                                      const char *RingBufferPtr,
                                      size_t RingBufferSize) {
     auto *RingBuffer =
         reinterpret_cast<const AllocationRingBuffer *>(RingBufferPtr);
     size_t RingBufferElements = ringBufferElementsFromBytes(RingBufferSize);
-    if (!RingBuffer || RingBufferElements == 0)
+    if (!RingBuffer || RingBufferElements == 0 || !RawStackDepot)
       return;
     uptr Pos = atomic_load_relaxed(&RingBuffer->Pos);
 
@@ -1460,9 +1484,10 @@ class Allocator {
 
       R->allocation_address = UntaggedEntryPtr;
       R->allocation_size = EntrySize;
-      collectTraceMaybe(Depot, R->allocation_trace, AllocationTrace);
+      collectTraceMaybe(RawStackDepot, R->allocation_trace, AllocationTrace);
       R->allocation_tid = AllocationTid;
-      collectTraceMaybe(Depot, R->deallocation_trace, DeallocationTrace);
+      collectTraceMaybe(RawStackDepot, R->deallocation_trace,
+                        DeallocationTrace);
       R->deallocation_tid = DeallocationTid;
     }
   }
@@ -1491,6 +1516,28 @@ class Allocator {
       return;
     u32 AllocationRingBufferSize =
         static_cast<u32>(getFlags()->allocation_ring_buffer_size);
+    // We store alloc and free stacks for each entry.
+    constexpr auto kStacksPerRingBufferEntry = 2;
+    u32 TabSize = static_cast<u32>(roundUpPowerOfTwo(kStacksPerRingBufferEntry *
+                                                     AllocationRingBufferSize));
+    constexpr auto kFramesPerStack = 8;
+    static_assert(isPowerOfTwo(kFramesPerStack));
+    u32 RingSize = static_cast<u32>(TabSize * kFramesPerStack);
+    DCHECK(isPowerOfTwo(RingSize));
+    static_assert(sizeof(StackDepot) % alignof(atomic_u64) == 0);
+
+    StackDepotSize = sizeof(StackDepot) + sizeof(atomic_u64) * RingSize +
+                     sizeof(atomic_u32) * TabSize;
+    MemMapT DepotMap;
+    DepotMap.map(
+        /*Addr=*/0U, roundUp(StackDepotSize, getPageSizeCached()),
+        "scudo:stack_depot");
+    RawStackDepot = reinterpret_cast<char *>(DepotMap.getBase());
+    auto *Depot = reinterpret_cast<StackDepot *>(DepotMap.getBase());
+    Depot->init(RingSize, TabSize);
+    DCHECK(Depot->isValid(StackDepotSize));
+    RawStackDepotMap = DepotMap;
+
     MemMapT MemMap;
     MemMap.map(
         /*Addr=*/0U,
@@ -1513,6 +1560,10 @@ class Allocator {
                              RawRingBufferMap.getCapacity());
     }
     RawRingBuffer = nullptr;
+    if (RawStackDepot) {
+      RawStackDepotMap.unmap(RawStackDepotMap.getBase(),
+                             RawStackDepotMap.getCapacity());
+    }
   }
 
   static constexpr size_t ringBufferSizeInBytes(u32 RingBufferElements) {
diff --git a/compiler-rt/lib/scudo/standalone/fuzz/get_error_info_fuzzer.cpp b/compiler-rt/lib/scudo/standalone/fuzz/get_error_info_fuzzer.cpp
index 5b01ebe11c09523..2cef1c44fadc9b8 100644
--- a/compiler-rt/lib/scudo/standalone/fuzz/get_error_info_fuzzer.cpp
+++ b/compiler-rt/lib/scudo/standalone/fuzz/get_error_info_fuzzer.cpp
@@ -9,6 +9,7 @@
 #define SCUDO_FUZZ
 #include "allocator_config.h"
 #include "combined.h"
+#include "common.h"
 
 #include <fuzzer/FuzzedDataProvider.h>
 
@@ -31,11 +32,6 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t *Data, size_t Size) {
 
   std::string StackDepotBytes =
       FDP.ConsumeRandomLengthString(FDP.remaining_bytes());
-  std::vector<char> StackDepot(sizeof(scudo::StackDepot), 0);
-  for (size_t i = 0; i < StackDepotBytes.length() && i < StackDepot.size();
-       ++i) {
-    StackDepot[i] = StackDepotBytes[i];
-  }
 
   std::string RegionInfoBytes =
       FDP.ConsumeRandomLengthString(FDP.remaining_bytes());
@@ -48,9 +44,9 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t *Data, size_t Size) {
   std::string RingBufferBytes = FDP.ConsumeRemainingBytesAsString();
 
   scudo_error_info ErrorInfo;
-  AllocatorT::getErrorInfo(&ErrorInfo, FaultAddr, StackDepot.data(),
-                           RegionInfo.data(), RingBufferBytes.data(),
-                           RingBufferBytes.size(), Memory, MemoryTags,
-                           MemoryAddr, MemorySize);
+  AllocatorT::getErrorInfo(&ErrorInfo, FaultAddr, StackDepotBytes.data(),
+                           StackDepotBytes.size(), RegionInfo.data(),
+                           RingBufferBytes.data(), RingBufferBytes.size(),
+                           Memory, MemoryTags, MemoryAddr, MemorySize);
   return 0;
 }
diff --git a/compiler-rt/lib/scudo/standalone/platform.h b/compiler-rt/lib/scudo/standalone/platform.h
index b71a86be7669f36..5af1275e32d2b6d 100644
--- a/compiler-rt/lib/scudo/standalone/platform.h
+++ b/compiler-rt/lib/scudo/standalone/platform.h
@@ -63,16 +63,6 @@
 #define SCUDO_CAN_USE_MTE (SCUDO_LINUX || SCUDO_TRUSTY)
 #endif
 
-// Use smaller table sizes for fuzzing in order to reduce input size.
-// Trusty just has less available memory.
-#ifndef SCUDO_SMALL_STACK_DEPOT
-#if defined(SCUDO_FUZZ) || SCUDO_TRUSTY
-#define SCUDO_SMALL_STACK_DEPOT 1
-#else
-#define SCUDO_SMALL_STACK_DEPOT 0
-#endif
-#endif
-
 #ifndef SCUDO_ENABLE_HOOKS
 #define SCUDO_ENABLE_HOOKS 0
 #endif
diff --git a/compiler-rt/lib/scudo/standalone/stack_depot.h b/compiler-rt/lib/scudo/standalone/stack_depot.h
index 12c35eb2a4f3383..9508e0a9ec755a5 100644
--- a/compiler-rt/lib/scudo/standalone/stack_depot.h
+++ b/compiler-rt/lib/scudo/standalone/stack_depot.h
@@ -10,6 +10,7 @@
 #define SCUDO_STACK_DEPOT_H_
 
 #include "atomic_helpers.h"
+#include "common.h"
 #include "mutex.h"
 
 namespace scudo {
@@ -38,7 +39,7 @@ class MurMur2HashBuilder {
   }
 };
 
-class StackDepot {
+class alignas(16) StackDepot {
   HybridMutex RingEndMu;
   u32 RingEnd = 0;
 
@@ -62,47 +63,103 @@ class StackDepot {
   // This is achieved by re-checking the hash of the stack trace before
   // returning the trace.
 
-#if SCUDO_SMALL_STACK_DEPOT
-  static const uptr TabBits = 4;
-#else
-  static const uptr TabBits = 16;
-#endif
-  static const uptr TabSize = 1 << TabBits;
-  static const uptr TabMask = TabSize - 1;
-  atomic_u32 Tab[TabSize] = {};
-
-#if SCUDO_SMALL_STACK_DEPOT
-  static const uptr RingBits = 4;
-#else
-  static const uptr RingBits = 19;
-#endif
-  static const uptr RingSize = 1 << RingBits;
-  static const uptr RingMask = RingSize - 1;
-  atomic_u64 Ring[RingSize] = {};
+  uptr RingSize = 0;
+  uptr RingMask = 0;
+  uptr TabMask = 0;
+  // This is immediately followed by RingSize atomic_u64 and
+  // (TabMask + 1) atomic_u32.
+
+  atomic_u64 *Ring(char *RawStackDepot) {
+    return reinterpret_cast<atomic_u64 *>(RawStackDepot + sizeof(StackDepot));
+  }
+
+  atomic_u32 *Tab(char *RawStackDepot) {
+    return reinterpret_cast<atomic_u32 *>(RawStackDepot + sizeof(StackDepot) +
+                                          sizeof(atomic_u64) * RingSize);
+  }
+
+  const atomic_u64 *Ring(const char *RawStackDepot) const {
+    return reinterpret_cast<const atomic_u64 *>(RawStackDepot +
+                                                sizeof(StackDepot));
+  }
+
+  const atomic_u32 *Tab(const char *RawStackDepot) const {
+    return reinterpret_cast<const atomic_u32 *>(
+        RawStackDepot + sizeof(StackDepot) + sizeof(atomic_u64) * RingSize);
+  }
 
 public:
+  void init(uptr RingSz, uptr TabSz) {
+    DCHECK(isPowerOfTwo(RingSz));
+    DCHECK(isPowerOfTwo(TabSz));
+    RingSize = RingSz;
+    RingMask = RingSz - 1;
+    TabMask = TabSz - 1;
+  }
+
+  // Ensure that RingSize, RingMask and TabMask are set up in a way that
+  // all accesses are within range of BufSize.
+  bool isValid(uptr BufSize) const {
+    if (RingSize > UINTPTR_MAX / sizeof(atomic_u64)) {
+      return false;
+    }
+    if (RingSize == 0 || !isPowerOfTwo(RingSize)) {
+      return false;
+    }
+    uptr RingBytes = sizeof(atomic_u64) * RingSize;
+    if (RingMask + 1 != RingSize) {
+      return false;
+    }
+
+    if (TabMask == 0) {
+      return false;
+    }
+    if ((TabMask - 1) > UINTPTR_MAX / sizeof(atomic_u32)) {
+      return false;
+    }
+    uptr TabSize = TabMask + 1;
+    if (!isPowerOfTwo(TabSize)) {
+      return false;
+    }
+    uptr TabBytes = sizeof(atomic_u32) * TabSize;
+
+    // Subtract and detect underflow.
+    if (BufSize < sizeof(StackDepot)) {
+      return false;
+    }
+    BufSize -= sizeof(StackDepot);
+    if (BufSize < TabBytes) {
+      return false;
+    }
+    BufSize = TabBytes;
+    if (BufSize < RingBytes) {
+      return false;
+    }
+    return BufSize == 0;
+  }
+
   // Insert hash of the stack trace [Begin, End) into the stack depot, and
   // return the hash.
-  u32 insert(uptr *Begin, uptr *End) {
+  u32 insert(char *RawStackDepot, uptr *Begin, uptr *End) {
     MurMur2HashBuilder B;
     for (uptr *I = Begin; I != End; ++I)
       B.add(u32(*I) >> 2);
     u32 Hash = B.get();
 
     u32 Pos = Hash & TabMask;
-    u32 RingPos = atomic_load_relaxed(&Tab[Pos]);
-    u64 Entry = atomic_load_relaxed(&Ring[RingPos]);
+    u32 RingPos = atomic_load_relaxed(&Tab(RawStackDepot)[Pos]);
+    u64 Entry = atomic_load_relaxed(&Ring(RawStackDepot)[RingPos]);
     u64 Id = (u64(End - Begin) << 33) | (u64(Hash) << 1) | 1;
     if (Entry == Id)
       return Hash;
 
     ScopedLock Lock(RingEndMu);
     RingPos = RingEnd;
-    atomic_store_relaxed(&Tab[Pos], RingPos);
-    atomic_store_relaxed(&Ring[RingPos], Id);
+    atomic_store_relaxed(&Tab(RawStackDepot)[Pos], RingPos);
+    atomic_store_relaxed(&Ring(RawStackDepot)[RingPos], Id);
     for (uptr *I = Begin; I != End; ++I) {
       RingPos = (RingPos + 1) & RingMask;
-      atomic_store_relaxed(&Ring[RingPos], *I);
+      atomic_store_relaxed(&Ring(RawStackDepot)[RingPos], *I);
     }
     RingEnd = (RingPos + 1) & RingMask;
     return Hash;
@@ -111,12 +168,13 @@ class StackDepot {
   // Look up a stack trace by hash. Returns true if successful. The trace may be
   // accessed via operator[] passing indexes between *RingPosPtr and
   // *RingPosPtr + *SizePtr.
-  bool find(u32 Hash, uptr *RingPosPtr, uptr *SizePtr) const {
+  bool find(const char *RawStackDepot, u32 Hash, uptr *RingPosPtr,
+            uptr *SizePtr) const {
     u32 Pos = Hash & TabMask;
-    u32 RingPos = atomic_load_relaxed(&Tab[Pos]);
+    u32 RingPos = atomic_load_relaxed(&Tab(RawStackDepot)[Pos]);
     if (RingPos >= RingSize)
       return false;
-    u64 Entry = atomic_load_relaxed(&Ring[RingPos]);
+    u64 Entry = atomic_load_relaxed(&Ring(RawStackDepot)[RingPos]);
     u64 HashWithTagBit = (u64(Hash) << 1) | 1;
     if ((Entry & 0x1ffffffff) != HashWithTagBit)
       return false;
@@ -128,13 +186,13 @@ class StackDepot {
     MurMur2HashBuilder B;
     for (uptr I = 0; I != Size; ++I) {
       RingPos = (RingPos + 1) & RingMask;
-      B.add(u32(atomic_load_relaxed(&Ring[RingPos])) >> 2);
+      B.add(u32(atomic_load_relaxed(&Ring(RawStackDepot)[RingPos])) >> 2);
     }
     return B.get() == Hash;
   }
 
-  u64 operator[](uptr RingPos) const {
-    return atomic_load_relaxed(&Ring[RingPos & RingMask]);
+  u64 at(const char *RawStackDepot, uptr RingPos) const {
+    return atomic_load_relaxed(&Ring(RawStackDepot)[RingPos & RingMask]);
   }
 };
 
diff --git a/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp b/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp
index 21694c3f17fe578..e9d8c1e8d3db2f5 100644
--- a/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp
+++ b/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp
@@ -43,10 +43,9 @@ INTERFACE void __scudo_get_error_info(
     const char *stack_depot, size_t stack_depot_size, const char *region_info,
     const char *ring_buffer, size_t ring_buffer_size, const char *memory,
     const char *memory_tags, uintptr_t memory_addr, size_t memory_size) {
-  (void)(stack_depot_size);
-  Allocator.getErrorInfo(error_info, fault_addr, stack_depot, region_info,
-                         ring_buffer, ring_buffer_size, memory, memory_tags,
-                         memory_addr, memory_size);
+  Allocator.getErrorInfo(error_info, fault_addr, stack_depot, stack_depot_size,
+                         region_info, ring_buffer, ring_buffer_size, memory,
+                         memory_tags, memory_addr, memory_size);
 }
 
 INTERFACE const char *__scudo_get_stack_depot_addr() {
@@ -54,7 +53,7 @@ INTERFACE const char *__scudo_get_stack_depot_addr() {
 }
 
 INTERFACE size_t __scudo_get_stack_depot_size() {
-  return sizeof(scudo::StackDepot);
+  return Allocator.getStackDepotSize();
 }
 
 INTERFACE const char *__scudo_get_region_info_addr() {

>From 9d0169bde9f5cf3718612f5d63058211feae3c72 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Wed, 13 Dec 2023 13:00:15 -0800
Subject: [PATCH 02/16] comments

---
 compiler-rt/lib/scudo/standalone/combined.h   | 27 +++++++++----
 .../lib/scudo/standalone/stack_depot.h        | 31 ++++++---------
 .../scudo/standalone/tests/combined_test.cpp  | 38 ++++++++++++++++++-
 3 files changed, 67 insertions(+), 29 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index 49cdc44cd80d266..cabc51339505cb4 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -9,6 +9,7 @@
 #ifndef SCUDO_COMBINED_H_
 #define SCUDO_COMBINED_H_
 
+#include "atomic_helpers.h"
 #include "chunk.h"
 #include "common.h"
 #include "flags.h"
@@ -965,18 +966,21 @@ class Allocator {
                            const char *RingBufferPtr, size_t RingBufferSize,
                            const char *Memory, const char *MemoryTags,
                            uintptr_t MemoryAddr, size_t MemorySize) {
+    // N.B. we need to support corrupted data in any of the buffers here. We get
+    // this information from an external process (the crashing process) that
+    // shouldn't be able to crash crash_dump.
     *ErrorInfo = {};
     if (!allocatorSupportsMemoryTagging<Config>() ||
         MemoryAddr + MemorySize < MemoryAddr)
       return;
 
-    if (DepotPtr && DepotSize < sizeof(StackDepot)) {
-      return;
-    }
-    if (DepotPtr &&
-        !reinterpret_cast<const StackDepot *>(DepotPtr)->isValid(DepotSize)) {
-      // corrupted stack depot.
-      return;
+    if (DepotPtr) {
+      // check for corrupted StackDepot. First we need to check whether we can
+      // read the metadata, then whether the metadata matches the size.
+      if (DepotSize < sizeof(StackDepot))
+        return;
+      if (!reinterpret_cast<const StackDepot *>(DepotPtr)->isValid(DepotSize))
+        return;
     }
 
     size_t NextErrorReport = 0;
@@ -1518,14 +1522,23 @@ class Allocator {
         static_cast<u32>(getFlags()->allocation_ring_buffer_size);
     // We store alloc and free stacks for each entry.
     constexpr auto kStacksPerRingBufferEntry = 2;
+    constexpr auto kMaxU32Pow2 = ~(UINT32_MAX >> 1);
+    static_assert(isPowerOfTwo(kMaxU32Pow2));
+    if (AllocationRingBufferSize > kMaxU32Pow2 / kStacksPerRingBufferEntry)
+      return;
     u32 TabSize = static_cast<u32>(roundUpPowerOfTwo(kStacksPerRingBufferEntry *
                                                      AllocationRingBufferSize));
     constexpr auto kFramesPerStack = 8;
     static_assert(isPowerOfTwo(kFramesPerStack));
+    if (TabSize > UINT32_MAX / kFramesPerStack)
+      return;
     u32 RingSize = static_cast<u32>(TabSize * kFramesPerStack);
     DCHECK(isPowerOfTwo(RingSize));
     static_assert(sizeof(StackDepot) % alignof(atomic_u64) == 0);
 
+    static_assert(sizeof(StackDepot) + UINT32_MAX * sizeof(atomic_u64) *
+                                           UINT32_MAX * sizeof(atomic_u32) <
+                  UINTPTR_MAX);
     StackDepotSize = sizeof(StackDepot) + sizeof(atomic_u64) * RingSize +
                      sizeof(atomic_u32) * TabSize;
     MemMapT DepotMap;
diff --git a/compiler-rt/lib/scudo/standalone/stack_depot.h b/compiler-rt/lib/scudo/standalone/stack_depot.h
index 9508e0a9ec755a5..072eb80f8157dbf 100644
--- a/compiler-rt/lib/scudo/standalone/stack_depot.h
+++ b/compiler-rt/lib/scudo/standalone/stack_depot.h
@@ -100,42 +100,33 @@ class alignas(16) StackDepot {
   // Ensure that RingSize, RingMask and TabMask are set up in a way that
   // all accesses are within range of BufSize.
   bool isValid(uptr BufSize) const {
-    if (RingSize > UINTPTR_MAX / sizeof(atomic_u64)) {
+    if (RingSize > UINTPTR_MAX / sizeof(atomic_u64))
       return false;
-    }
-    if (RingSize == 0 || !isPowerOfTwo(RingSize)) {
+    if (RingSize == 0 || !isPowerOfTwo(RingSize))
       return false;
-    }
     uptr RingBytes = sizeof(atomic_u64) * RingSize;
-    if (RingMask + 1 != RingSize) {
+    if (RingMask + 1 != RingSize)
       return false;
-    }
 
-    if (TabMask == 0) {
+    if (TabMask == 0)
       return false;
-    }
-    if ((TabMask - 1) > UINTPTR_MAX / sizeof(atomic_u32)) {
+    if ((TabMask - 1) > UINTPTR_MAX / sizeof(atomic_u32))
       return false;
-    }
     uptr TabSize = TabMask + 1;
-    if (!isPowerOfTwo(TabSize)) {
+    if (!isPowerOfTwo(TabSize))
       return false;
-    }
     uptr TabBytes = sizeof(atomic_u32) * TabSize;
 
     // Subtract and detect underflow.
-    if (BufSize < sizeof(StackDepot)) {
+    if (BufSize < sizeof(StackDepot))
       return false;
-    }
     BufSize -= sizeof(StackDepot);
-    if (BufSize < TabBytes) {
+    if (BufSize < TabBytes)
       return false;
-    }
-    BufSize = TabBytes;
-    if (BufSize < RingBytes) {
+    BufSize -= TabBytes;
+    if (BufSize < RingBytes)
       return false;
-    }
-    return BufSize == 0;
+    return BufSize == RingBytes;
   }
 
   // Insert hash of the stack trace [Begin, End) into the stack depot, and
diff --git a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
index 3dbd93cacefd684..80898e5a10083c2 100644
--- a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "memtag.h"
+#include "stack_depot.h"
 #include "tests/scudo_unit_test.h"
 
 #include "allocator_config.h"
@@ -860,8 +861,8 @@ SCUDO_TYPED_TEST(ScudoCombinedTest, ReallocateInPlaceStress) {
 SCUDO_TYPED_TEST(ScudoCombinedTest, RingBufferSize) {
   auto *Allocator = this->Allocator.get();
   auto Size = Allocator->getRingBufferSize();
-  if (Size > 0)
-    EXPECT_EQ(Allocator->getRingBufferAddress()[Size - 1], '\0');
+  ASSERT_GT(Size, 0);
+  EXPECT_EQ(Allocator->getRingBufferAddress()[Size - 1], '\0');
 }
 
 SCUDO_TYPED_TEST(ScudoCombinedTest, RingBufferAddress) {
@@ -871,6 +872,39 @@ SCUDO_TYPED_TEST(ScudoCombinedTest, RingBufferAddress) {
   EXPECT_EQ(Addr, Allocator->getRingBufferAddress());
 }
 
+SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepotSize) {
+  auto *Allocator = this->Allocator.get();
+  auto Size = Allocator->getStackDepotSize();
+  ASSERT_GT(Size, 0);
+  EXPECT_EQ(Allocator->getStackDepotAddress()[Size - 1], '\0');
+}
+
+SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepotAddress) {
+  auto *Allocator = this->Allocator.get();
+  auto *Addr = Allocator->getStackDepotAddress();
+  EXPECT_NE(Addr, nullptr);
+  EXPECT_EQ(Addr, Allocator->getStackDepotAddress());
+}
+
+SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepot) {
+  alignas(scudo::StackDepot) char Buf[sizeof(scudo::StackDepot) +
+                                      1024 * sizeof(scudo::atomic_u64) +
+                                      1024 * sizeof(scudo::atomic_u32)] = {};
+  auto *Depot = reinterpret_cast<scudo::StackDepot *>(Buf);
+  Depot->init(1024, 1024);
+  ASSERT_TRUE(Depot->isValid(sizeof(Buf)));
+  ASSERT_FALSE(Depot->isValid(sizeof(Buf) - 1));
+  scudo::uptr Stack[] = {1, 2, 3};
+  scudo::u32 Elem = Depot->insert(Buf, &Stack[0], &Stack[3]);
+  scudo::uptr RingPosPtr = 0;
+  scudo::uptr SizePtr = 0;
+  ASSERT_TRUE(Depot->find(Buf, Elem, &RingPosPtr, &SizePtr));
+  ASSERT_EQ(SizePtr, 3);
+  EXPECT_EQ(Depot->at(Buf, RingPosPtr), 1);
+  EXPECT_EQ(Depot->at(Buf, RingPosPtr + 1), 2);
+  EXPECT_EQ(Depot->at(Buf, RingPosPtr + 2), 3);
+}
+
 #if SCUDO_CAN_USE_PRIMARY64
 #if SCUDO_TRUSTY
 

>From 6d7d99663af3f0c025ff6d50758f215c2db96f73 Mon Sep 17 00:00:00 2001
From: Florian Mayer <florian.mayer at bitsrc.org>
Date: Wed, 13 Dec 2023 15:49:47 -0800
Subject: [PATCH 03/16] Update compiler-rt/lib/scudo/standalone/stack_depot.h

Co-authored-by: ChiaHungDuan <f103119 at gmail.com>
---
 compiler-rt/lib/scudo/standalone/stack_depot.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/stack_depot.h b/compiler-rt/lib/scudo/standalone/stack_depot.h
index 072eb80f8157dbf..e7caa8a3d9b5dc9 100644
--- a/compiler-rt/lib/scudo/standalone/stack_depot.h
+++ b/compiler-rt/lib/scudo/standalone/stack_depot.h
@@ -138,8 +138,12 @@ class alignas(16) StackDepot {
     u32 Hash = B.get();
 
     u32 Pos = Hash & TabMask;
-    u32 RingPos = atomic_load_relaxed(&Tab(RawStackDepot)[Pos]);
-    u64 Entry = atomic_load_relaxed(&Ring(RawStackDepot)[RingPos]);
+   atomic_u32 *Tab = getTab(RawStackDepot);
+   atomic_u64 *Ring = getRing(RawStackDepot);
+   u32 RingPos = atomic_load_relaxed(&Tab[Pos]);
+   u64 Entry = atomic_load_relaxed(&Ring[RingPos]);
+   
+   // And the following uses of Tab/Ring
     u64 Id = (u64(End - Begin) << 33) | (u64(Hash) << 1) | 1;
     if (Entry == Id)
       return Hash;

>From faeaa216bbf2bf179df1a37c33ddd6e9468f4e32 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Wed, 13 Dec 2023 15:53:52 -0800
Subject: [PATCH 04/16] fmt suggestion

---
 compiler-rt/lib/scudo/standalone/stack_depot.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/stack_depot.h b/compiler-rt/lib/scudo/standalone/stack_depot.h
index e7caa8a3d9b5dc9..1699d5be1e70d86 100644
--- a/compiler-rt/lib/scudo/standalone/stack_depot.h
+++ b/compiler-rt/lib/scudo/standalone/stack_depot.h
@@ -138,12 +138,12 @@ class alignas(16) StackDepot {
     u32 Hash = B.get();
 
     u32 Pos = Hash & TabMask;
-   atomic_u32 *Tab = getTab(RawStackDepot);
-   atomic_u64 *Ring = getRing(RawStackDepot);
-   u32 RingPos = atomic_load_relaxed(&Tab[Pos]);
-   u64 Entry = atomic_load_relaxed(&Ring[RingPos]);
-   
-   // And the following uses of Tab/Ring
+    atomic_u32 *Tab = getTab(RawStackDepot);
+    atomic_u64 *Ring = getRing(RawStackDepot);
+    u32 RingPos = atomic_load_relaxed(&Tab[Pos]);
+    u64 Entry = atomic_load_relaxed(&Ring[RingPos]);
+
+    // And the following uses of Tab/Ring
     u64 Id = (u64(End - Begin) << 33) | (u64(Hash) << 1) | 1;
     if (Entry == Id)
       return Hash;

>From 2e237e98000041896a4064fa4034dd5f34c3b031 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Wed, 13 Dec 2023 15:59:47 -0800
Subject: [PATCH 05/16] Revert "fmt suggestion"

This reverts commit 86963399a908e4317a4fa8a47b9e7bb51ee7d7a5.
---
 compiler-rt/lib/scudo/standalone/stack_depot.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/stack_depot.h b/compiler-rt/lib/scudo/standalone/stack_depot.h
index 1699d5be1e70d86..e7caa8a3d9b5dc9 100644
--- a/compiler-rt/lib/scudo/standalone/stack_depot.h
+++ b/compiler-rt/lib/scudo/standalone/stack_depot.h
@@ -138,12 +138,12 @@ class alignas(16) StackDepot {
     u32 Hash = B.get();
 
     u32 Pos = Hash & TabMask;
-    atomic_u32 *Tab = getTab(RawStackDepot);
-    atomic_u64 *Ring = getRing(RawStackDepot);
-    u32 RingPos = atomic_load_relaxed(&Tab[Pos]);
-    u64 Entry = atomic_load_relaxed(&Ring[RingPos]);
-
-    // And the following uses of Tab/Ring
+   atomic_u32 *Tab = getTab(RawStackDepot);
+   atomic_u64 *Ring = getRing(RawStackDepot);
+   u32 RingPos = atomic_load_relaxed(&Tab[Pos]);
+   u64 Entry = atomic_load_relaxed(&Ring[RingPos]);
+   
+   // And the following uses of Tab/Ring
     u64 Id = (u64(End - Begin) << 33) | (u64(Hash) << 1) | 1;
     if (Entry == Id)
       return Hash;

>From 8ff895204599ef06c5d30d388f3cc84a288f5991 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Wed, 13 Dec 2023 15:59:54 -0800
Subject: [PATCH 06/16] Revert "Update
 compiler-rt/lib/scudo/standalone/stack_depot.h"

This reverts commit 3ff01eacd0fe13da16b83c86abe216cdb423caef.
---
 compiler-rt/lib/scudo/standalone/stack_depot.h | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/stack_depot.h b/compiler-rt/lib/scudo/standalone/stack_depot.h
index e7caa8a3d9b5dc9..072eb80f8157dbf 100644
--- a/compiler-rt/lib/scudo/standalone/stack_depot.h
+++ b/compiler-rt/lib/scudo/standalone/stack_depot.h
@@ -138,12 +138,8 @@ class alignas(16) StackDepot {
     u32 Hash = B.get();
 
     u32 Pos = Hash & TabMask;
-   atomic_u32 *Tab = getTab(RawStackDepot);
-   atomic_u64 *Ring = getRing(RawStackDepot);
-   u32 RingPos = atomic_load_relaxed(&Tab[Pos]);
-   u64 Entry = atomic_load_relaxed(&Ring[RingPos]);
-   
-   // And the following uses of Tab/Ring
+    u32 RingPos = atomic_load_relaxed(&Tab(RawStackDepot)[Pos]);
+    u64 Entry = atomic_load_relaxed(&Ring(RawStackDepot)[RingPos]);
     u64 Id = (u64(End - Begin) << 33) | (u64(Hash) << 1) | 1;
     if (Entry == Id)
       return Hash;

>From ec3a0699f7a2d7dcc9812a7e866f7f9abf3b2e6e Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Tue, 23 Jan 2024 15:40:38 -0800
Subject: [PATCH 07/16] review

---
 .../lib/scudo/standalone/stack_depot.h        | 33 +++++++++++--------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/stack_depot.h b/compiler-rt/lib/scudo/standalone/stack_depot.h
index 072eb80f8157dbf..a6ccd679aabaf38 100644
--- a/compiler-rt/lib/scudo/standalone/stack_depot.h
+++ b/compiler-rt/lib/scudo/standalone/stack_depot.h
@@ -69,21 +69,21 @@ class alignas(16) StackDepot {
   // This is immediately followed by RingSize atomic_u64 and
   // (TabMask + 1) atomic_u32.
 
-  atomic_u64 *Ring(char *RawStackDepot) {
+  atomic_u64 *getRing(char *RawStackDepot) {
     return reinterpret_cast<atomic_u64 *>(RawStackDepot + sizeof(StackDepot));
   }
 
-  atomic_u32 *Tab(char *RawStackDepot) {
+  atomic_u32 *getTab(char *RawStackDepot) {
     return reinterpret_cast<atomic_u32 *>(RawStackDepot + sizeof(StackDepot) +
                                           sizeof(atomic_u64) * RingSize);
   }
 
-  const atomic_u64 *Ring(const char *RawStackDepot) const {
+  const atomic_u64 *getRing(const char *RawStackDepot) const {
     return reinterpret_cast<const atomic_u64 *>(RawStackDepot +
                                                 sizeof(StackDepot));
   }
 
-  const atomic_u32 *Tab(const char *RawStackDepot) const {
+  const atomic_u32 *getTab(const char *RawStackDepot) const {
     return reinterpret_cast<const atomic_u32 *>(
         RawStackDepot + sizeof(StackDepot) + sizeof(atomic_u64) * RingSize);
   }
@@ -132,25 +132,28 @@ class alignas(16) StackDepot {
   // Insert hash of the stack trace [Begin, End) into the stack depot, and
   // return the hash.
   u32 insert(char *RawStackDepot, uptr *Begin, uptr *End) {
+    auto *Tab = getTab(RawStackDepot);
+    auto *Ring = getRing(RawStackDepot);
+
     MurMur2HashBuilder B;
     for (uptr *I = Begin; I != End; ++I)
       B.add(u32(*I) >> 2);
     u32 Hash = B.get();
 
     u32 Pos = Hash & TabMask;
-    u32 RingPos = atomic_load_relaxed(&Tab(RawStackDepot)[Pos]);
-    u64 Entry = atomic_load_relaxed(&Ring(RawStackDepot)[RingPos]);
+    u32 RingPos = atomic_load_relaxed(&Tab[Pos]);
+    u64 Entry = atomic_load_relaxed(&Ring[RingPos]);
     u64 Id = (u64(End - Begin) << 33) | (u64(Hash) << 1) | 1;
     if (Entry == Id)
       return Hash;
 
     ScopedLock Lock(RingEndMu);
     RingPos = RingEnd;
-    atomic_store_relaxed(&Tab(RawStackDepot)[Pos], RingPos);
-    atomic_store_relaxed(&Ring(RawStackDepot)[RingPos], Id);
+    atomic_store_relaxed(&Tab[Pos], RingPos);
+    atomic_store_relaxed(&Ring[RingPos], Id);
     for (uptr *I = Begin; I != End; ++I) {
       RingPos = (RingPos + 1) & RingMask;
-      atomic_store_relaxed(&Ring(RawStackDepot)[RingPos], *I);
+      atomic_store_relaxed(&Ring[RingPos], *I);
     }
     RingEnd = (RingPos + 1) & RingMask;
     return Hash;
@@ -161,11 +164,14 @@ class alignas(16) StackDepot {
   // *RingPosPtr + *SizePtr.
   bool find(const char *RawStackDepot, u32 Hash, uptr *RingPosPtr,
             uptr *SizePtr) const {
+    auto *Tab = getTab(RawStackDepot);
+    auto *Ring = getRing(RawStackDepot);
+
     u32 Pos = Hash & TabMask;
-    u32 RingPos = atomic_load_relaxed(&Tab(RawStackDepot)[Pos]);
+    u32 RingPos = atomic_load_relaxed(&Tab[Pos]);
     if (RingPos >= RingSize)
       return false;
-    u64 Entry = atomic_load_relaxed(&Ring(RawStackDepot)[RingPos]);
+    u64 Entry = atomic_load_relaxed(&Ring[RingPos]);
     u64 HashWithTagBit = (u64(Hash) << 1) | 1;
     if ((Entry & 0x1ffffffff) != HashWithTagBit)
       return false;
@@ -177,13 +183,14 @@ class alignas(16) StackDepot {
     MurMur2HashBuilder B;
     for (uptr I = 0; I != Size; ++I) {
       RingPos = (RingPos + 1) & RingMask;
-      B.add(u32(atomic_load_relaxed(&Ring(RawStackDepot)[RingPos])) >> 2);
+      B.add(u32(atomic_load_relaxed(&Ring[RingPos])) >> 2);
     }
     return B.get() == Hash;
   }
 
   u64 at(const char *RawStackDepot, uptr RingPos) const {
-    return atomic_load_relaxed(&Ring(RawStackDepot)[RingPos & RingMask]);
+    auto *Ring = getRing(RawStackDepot);
+    return atomic_load_relaxed(&Ring[RingPos & RingMask]);
   }
 };
 

>From 366bb7ee40194d867faa71467d327a41b07f9d59 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Tue, 23 Jan 2024 16:20:33 -0800
Subject: [PATCH 08/16] rearrange

---
 compiler-rt/lib/scudo/standalone/combined.h | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index cabc51339505cb4..0f8dcb34c16d09d 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -1520,25 +1520,33 @@ class Allocator {
       return;
     u32 AllocationRingBufferSize =
         static_cast<u32>(getFlags()->allocation_ring_buffer_size);
+
     // We store alloc and free stacks for each entry.
     constexpr auto kStacksPerRingBufferEntry = 2;
     constexpr auto kMaxU32Pow2 = ~(UINT32_MAX >> 1);
     static_assert(isPowerOfTwo(kMaxU32Pow2));
+    constexpr auto kFramesPerStack = 8;
+    static_assert(isPowerOfTwo(kFramesPerStack));
+
+    // We need StackDepot to be aligned to 8-bytes so the ring we st ore after
+    // is correctly assigned.
+    static_assert(sizeof(StackDepot) % alignof(atomic_u64) == 0);
+
+    // Make sure the maximum sized StackDepot fits withint a uintptr_t to
+    // simplify the overflow checking.
+    static_assert(sizeof(StackDepot) + UINT32_MAX * sizeof(atomic_u64) *
+                                           UINT32_MAX * sizeof(atomic_u32) <
+                  UINTPTR_MAX);
+
     if (AllocationRingBufferSize > kMaxU32Pow2 / kStacksPerRingBufferEntry)
       return;
     u32 TabSize = static_cast<u32>(roundUpPowerOfTwo(kStacksPerRingBufferEntry *
                                                      AllocationRingBufferSize));
-    constexpr auto kFramesPerStack = 8;
-    static_assert(isPowerOfTwo(kFramesPerStack));
     if (TabSize > UINT32_MAX / kFramesPerStack)
       return;
     u32 RingSize = static_cast<u32>(TabSize * kFramesPerStack);
     DCHECK(isPowerOfTwo(RingSize));
-    static_assert(sizeof(StackDepot) % alignof(atomic_u64) == 0);
 
-    static_assert(sizeof(StackDepot) + UINT32_MAX * sizeof(atomic_u64) *
-                                           UINT32_MAX * sizeof(atomic_u32) <
-                  UINTPTR_MAX);
     StackDepotSize = sizeof(StackDepot) + sizeof(atomic_u64) * RingSize +
                      sizeof(atomic_u32) * TabSize;
     MemMapT DepotMap;

>From ec49bf9e669b1c88098d850549dd13cdd3900925 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Tue, 23 Jan 2024 16:41:12 -0800
Subject: [PATCH 09/16] typo

---
 compiler-rt/lib/scudo/standalone/combined.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index 0f8dcb34c16d09d..0aef9cf8520c121 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -1528,7 +1528,7 @@ class Allocator {
     constexpr auto kFramesPerStack = 8;
     static_assert(isPowerOfTwo(kFramesPerStack));
 
-    // We need StackDepot to be aligned to 8-bytes so the ring we st ore after
+    // We need StackDepot to be aligned to 8-bytes so the ring we store after
     // is correctly assigned.
     static_assert(sizeof(StackDepot) % alignof(atomic_u64) == 0);
 

>From 907737bec3fae27e2b6d52c0f7446bfb1893c539 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Tue, 23 Jan 2024 17:15:02 -0800
Subject: [PATCH 10/16] review

---
 compiler-rt/lib/scudo/standalone/combined.h   | 27 +++++++------
 .../lib/scudo/standalone/stack_depot.h        | 38 ++++++++++---------
 .../scudo/standalone/tests/combined_test.cpp  | 10 ++---
 3 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index 0aef9cf8520c121..c39922d95b5fbe5 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -291,9 +291,8 @@ class Allocator {
     uptr Size =
         android_unsafe_frame_pointer_chase(Stack, MaxTraceSize + DiscardFrames);
     Size = Min<uptr>(Size, MaxTraceSize + DiscardFrames);
-    return reinterpret_cast<StackDepot *>(RawStackDepot)
-        ->insert(RawStackDepot, Stack + Min<uptr>(DiscardFrames, Size),
-                 Stack + Size);
+    return StackDepot->insert(Stack + Min<uptr>(DiscardFrames, Size),
+                              Stack + Size);
 #else
     return 0;
 #endif
@@ -922,7 +921,7 @@ class Allocator {
 
   const char *getStackDepotAddress() {
     initThreadMaybe();
-    return RawStackDepot;
+    return reinterpret_cast<char *>(StackDepot);
   }
 
   uptr getStackDepotSize() {
@@ -952,12 +951,12 @@ class Allocator {
 
   static void collectTraceMaybe(const char *RawStackDepot,
                                 uintptr_t (&Trace)[MaxTraceSize], u32 Hash) {
-    auto *Depot = reinterpret_cast<const StackDepot *>(RawStackDepot);
+    auto *Depot = reinterpret_cast<const class StackDepot *>(RawStackDepot);
     uptr RingPos, Size;
-    if (!Depot->find(RawStackDepot, Hash, &RingPos, &Size))
+    if (!Depot->find(Hash, &RingPos, &Size))
       return;
     for (unsigned I = 0; I != Size && I != MaxTraceSize; ++I)
-      Trace[I] = static_cast<uintptr_t>(Depot->at(RawStackDepot, RingPos + I));
+      Trace[I] = static_cast<uintptr_t>(Depot->at(RingPos + I));
   }
 
   static void getErrorInfo(struct scudo_error_info *ErrorInfo,
@@ -979,7 +978,8 @@ class Allocator {
       // read the metadata, then whether the metadata matches the size.
       if (DepotSize < sizeof(StackDepot))
         return;
-      if (!reinterpret_cast<const StackDepot *>(DepotPtr)->isValid(DepotSize))
+      if (!reinterpret_cast<const class StackDepot *>(DepotPtr)->isValid(
+              DepotSize))
         return;
     }
 
@@ -1048,7 +1048,7 @@ class Allocator {
   uptr GuardedAllocSlotSize = 0;
 #endif // GWP_ASAN_HOOKS
 
-  char *RawStackDepot = nullptr;
+  StackDepot *StackDepot = nullptr;
   uptr StackDepotSize = 0;
   MemMapT RawStackDepotMap;
 
@@ -1553,10 +1553,9 @@ class Allocator {
     DepotMap.map(
         /*Addr=*/0U, roundUp(StackDepotSize, getPageSizeCached()),
         "scudo:stack_depot");
-    RawStackDepot = reinterpret_cast<char *>(DepotMap.getBase());
-    auto *Depot = reinterpret_cast<StackDepot *>(DepotMap.getBase());
-    Depot->init(RingSize, TabSize);
-    DCHECK(Depot->isValid(StackDepotSize));
+    StackDepot = reinterpret_cast<class StackDepot *>(DepotMap.getBase());
+    StackDepot->init(RingSize, TabSize);
+    DCHECK(StackDepot->isValid(StackDepotSize));
     RawStackDepotMap = DepotMap;
 
     MemMapT MemMap;
@@ -1581,7 +1580,7 @@ class Allocator {
                              RawRingBufferMap.getCapacity());
     }
     RawRingBuffer = nullptr;
-    if (RawStackDepot) {
+    if (StackDepot) {
       RawStackDepotMap.unmap(RawStackDepotMap.getBase(),
                              RawStackDepotMap.getCapacity());
     }
diff --git a/compiler-rt/lib/scudo/standalone/stack_depot.h b/compiler-rt/lib/scudo/standalone/stack_depot.h
index a6ccd679aabaf38..5113608dfcf2695 100644
--- a/compiler-rt/lib/scudo/standalone/stack_depot.h
+++ b/compiler-rt/lib/scudo/standalone/stack_depot.h
@@ -69,23 +69,26 @@ class alignas(16) StackDepot {
   // This is immediately followed by RingSize atomic_u64 and
   // (TabMask + 1) atomic_u32.
 
-  atomic_u64 *getRing(char *RawStackDepot) {
-    return reinterpret_cast<atomic_u64 *>(RawStackDepot + sizeof(StackDepot));
+  atomic_u64 *getRing() {
+    return reinterpret_cast<atomic_u64 *>(reinterpret_cast<char *>(this) +
+                                          sizeof(StackDepot));
   }
 
-  atomic_u32 *getTab(char *RawStackDepot) {
-    return reinterpret_cast<atomic_u32 *>(RawStackDepot + sizeof(StackDepot) +
+  atomic_u32 *getTab() {
+    return reinterpret_cast<atomic_u32 *>(reinterpret_cast<char *>(this) +
+                                          sizeof(StackDepot) +
                                           sizeof(atomic_u64) * RingSize);
   }
 
-  const atomic_u64 *getRing(const char *RawStackDepot) const {
-    return reinterpret_cast<const atomic_u64 *>(RawStackDepot +
-                                                sizeof(StackDepot));
+  const atomic_u64 *getRing() const {
+    return reinterpret_cast<const atomic_u64 *>(
+        reinterpret_cast<const char *>(this) + sizeof(StackDepot));
   }
 
-  const atomic_u32 *getTab(const char *RawStackDepot) const {
+  const atomic_u32 *getTab() const {
     return reinterpret_cast<const atomic_u32 *>(
-        RawStackDepot + sizeof(StackDepot) + sizeof(atomic_u64) * RingSize);
+        reinterpret_cast<const char *>(this) + sizeof(StackDepot) +
+        sizeof(atomic_u64) * RingSize);
   }
 
 public:
@@ -131,9 +134,9 @@ class alignas(16) StackDepot {
 
   // Insert hash of the stack trace [Begin, End) into the stack depot, and
   // return the hash.
-  u32 insert(char *RawStackDepot, uptr *Begin, uptr *End) {
-    auto *Tab = getTab(RawStackDepot);
-    auto *Ring = getRing(RawStackDepot);
+  u32 insert(uptr *Begin, uptr *End) {
+    auto *Tab = getTab();
+    auto *Ring = getRing();
 
     MurMur2HashBuilder B;
     for (uptr *I = Begin; I != End; ++I)
@@ -162,10 +165,9 @@ class alignas(16) StackDepot {
   // Look up a stack trace by hash. Returns true if successful. The trace may be
   // accessed via operator[] passing indexes between *RingPosPtr and
   // *RingPosPtr + *SizePtr.
-  bool find(const char *RawStackDepot, u32 Hash, uptr *RingPosPtr,
-            uptr *SizePtr) const {
-    auto *Tab = getTab(RawStackDepot);
-    auto *Ring = getRing(RawStackDepot);
+  bool find(u32 Hash, uptr *RingPosPtr, uptr *SizePtr) const {
+    auto *Tab = getTab();
+    auto *Ring = getRing();
 
     u32 Pos = Hash & TabMask;
     u32 RingPos = atomic_load_relaxed(&Tab[Pos]);
@@ -188,8 +190,8 @@ class alignas(16) StackDepot {
     return B.get() == Hash;
   }
 
-  u64 at(const char *RawStackDepot, uptr RingPos) const {
-    auto *Ring = getRing(RawStackDepot);
+  u64 at(uptr RingPos) const {
+    auto *Ring = getRing();
     return atomic_load_relaxed(&Ring[RingPos & RingMask]);
   }
 };
diff --git a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
index 80898e5a10083c2..cd9200793754a5c 100644
--- a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
@@ -895,14 +895,14 @@ SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepot) {
   ASSERT_TRUE(Depot->isValid(sizeof(Buf)));
   ASSERT_FALSE(Depot->isValid(sizeof(Buf) - 1));
   scudo::uptr Stack[] = {1, 2, 3};
-  scudo::u32 Elem = Depot->insert(Buf, &Stack[0], &Stack[3]);
+  scudo::u32 Elem = Depot->insert(&Stack[0], &Stack[3]);
   scudo::uptr RingPosPtr = 0;
   scudo::uptr SizePtr = 0;
-  ASSERT_TRUE(Depot->find(Buf, Elem, &RingPosPtr, &SizePtr));
+  ASSERT_TRUE(Depot->find(Elem, &RingPosPtr, &SizePtr));
   ASSERT_EQ(SizePtr, 3);
-  EXPECT_EQ(Depot->at(Buf, RingPosPtr), 1);
-  EXPECT_EQ(Depot->at(Buf, RingPosPtr + 1), 2);
-  EXPECT_EQ(Depot->at(Buf, RingPosPtr + 2), 3);
+  EXPECT_EQ(Depot->at(RingPosPtr), 1);
+  EXPECT_EQ(Depot->at(RingPosPtr + 1), 2);
+  EXPECT_EQ(Depot->at(RingPosPtr + 2), 3);
 }
 
 #if SCUDO_CAN_USE_PRIMARY64

>From 383ea9a34dd2488dd929b75db77e7375e01221a2 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Tue, 23 Jan 2024 17:17:30 -0800
Subject: [PATCH 11/16] simplify

---
 compiler-rt/lib/scudo/standalone/combined.h | 27 ++++++++++-----------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index c39922d95b5fbe5..794034ee2970b48 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -921,7 +921,7 @@ class Allocator {
 
   const char *getStackDepotAddress() {
     initThreadMaybe();
-    return reinterpret_cast<char *>(StackDepot);
+    return reinterpret_cast<char *>(Depot);
   }
 
   uptr getStackDepotSize() {
@@ -951,7 +951,7 @@ class Allocator {
 
   static void collectTraceMaybe(const char *RawStackDepot,
                                 uintptr_t (&Trace)[MaxTraceSize], u32 Hash) {
-    auto *Depot = reinterpret_cast<const class StackDepot *>(RawStackDepot);
+    auto *Depot = reinterpret_cast<const StackDepot *>(RawStackDepot);
     uptr RingPos, Size;
     if (!Depot->find(Hash, &RingPos, &Size))
       return;
@@ -976,10 +976,9 @@ class Allocator {
     if (DepotPtr) {
       // check for corrupted StackDepot. First we need to check whether we can
       // read the metadata, then whether the metadata matches the size.
-      if (DepotSize < sizeof(StackDepot))
+      if (DepotSize < sizeof(Depot))
         return;
-      if (!reinterpret_cast<const class StackDepot *>(DepotPtr)->isValid(
-              DepotSize))
+      if (!reinterpret_cast<const StackDepot *>(DepotPtr)->isValid(DepotSize))
         return;
     }
 
@@ -1048,7 +1047,7 @@ class Allocator {
   uptr GuardedAllocSlotSize = 0;
 #endif // GWP_ASAN_HOOKS
 
-  StackDepot *StackDepot = nullptr;
+  StackDepot *Depot = nullptr;
   uptr StackDepotSize = 0;
   MemMapT RawStackDepotMap;
 
@@ -1530,12 +1529,12 @@ class Allocator {
 
     // We need StackDepot to be aligned to 8-bytes so the ring we store after
     // is correctly assigned.
-    static_assert(sizeof(StackDepot) % alignof(atomic_u64) == 0);
+    static_assert(sizeof(Depot) % alignof(atomic_u64) == 0);
 
     // Make sure the maximum sized StackDepot fits withint a uintptr_t to
     // simplify the overflow checking.
-    static_assert(sizeof(StackDepot) + UINT32_MAX * sizeof(atomic_u64) *
-                                           UINT32_MAX * sizeof(atomic_u32) <
+    static_assert(sizeof(Depot) + UINT32_MAX * sizeof(atomic_u64) * UINT32_MAX *
+                                      sizeof(atomic_u32) <
                   UINTPTR_MAX);
 
     if (AllocationRingBufferSize > kMaxU32Pow2 / kStacksPerRingBufferEntry)
@@ -1547,15 +1546,15 @@ class Allocator {
     u32 RingSize = static_cast<u32>(TabSize * kFramesPerStack);
     DCHECK(isPowerOfTwo(RingSize));
 
-    StackDepotSize = sizeof(StackDepot) + sizeof(atomic_u64) * RingSize +
+    StackDepotSize = sizeof(Depot) + sizeof(atomic_u64) * RingSize +
                      sizeof(atomic_u32) * TabSize;
     MemMapT DepotMap;
     DepotMap.map(
         /*Addr=*/0U, roundUp(StackDepotSize, getPageSizeCached()),
         "scudo:stack_depot");
-    StackDepot = reinterpret_cast<class StackDepot *>(DepotMap.getBase());
-    StackDepot->init(RingSize, TabSize);
-    DCHECK(StackDepot->isValid(StackDepotSize));
+    Depot = reinterpret_cast<StackDepot *>(DepotMap.getBase());
+    Depot->init(RingSize, TabSize);
+    DCHECK(Depot->isValid(StackDepotSize));
     RawStackDepotMap = DepotMap;
 
     MemMapT MemMap;
@@ -1580,7 +1579,7 @@ class Allocator {
                              RawRingBufferMap.getCapacity());
     }
     RawRingBuffer = nullptr;
-    if (StackDepot) {
+    if (Depot) {
       RawStackDepotMap.unmap(RawStackDepotMap.getBase(),
                              RawStackDepotMap.getCapacity());
     }

>From e3bdafc7abd2fbd1b90c56e208fa4713bff2869d Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Tue, 23 Jan 2024 17:22:30 -0800
Subject: [PATCH 12/16] fix

---
 compiler-rt/lib/scudo/standalone/combined.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index 794034ee2970b48..e055b4946e969e7 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -291,8 +291,8 @@ class Allocator {
     uptr Size =
         android_unsafe_frame_pointer_chase(Stack, MaxTraceSize + DiscardFrames);
     Size = Min<uptr>(Size, MaxTraceSize + DiscardFrames);
-    return StackDepot->insert(Stack + Min<uptr>(DiscardFrames, Size),
-                              Stack + Size);
+    return Depot->insert(Stack + Min<uptr>(DiscardFrames, Size),
+                         Stack + Size);
 #else
     return 0;
 #endif

>From 35b4ea4c92fca327abe4795c3b60176b199a252b Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Tue, 23 Jan 2024 17:25:27 -0800
Subject: [PATCH 13/16] comment

---
 compiler-rt/lib/scudo/standalone/combined.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index e055b4946e969e7..2b72de0382b3102 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -967,7 +967,8 @@ class Allocator {
                            uintptr_t MemoryAddr, size_t MemorySize) {
     // N.B. we need to support corrupted data in any of the buffers here. We get
     // this information from an external process (the crashing process) that
-    // shouldn't be able to crash crash_dump.
+    // should not be able to crash the crash dumper (crash_dump on Android).
+    // See also the get_error_info_fuzzer.
     *ErrorInfo = {};
     if (!allocatorSupportsMemoryTagging<Config>() ||
         MemoryAddr + MemorySize < MemoryAddr)

>From 35a9f7606b636f6082846abcf7a0d29541da7607 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Tue, 23 Jan 2024 17:31:41 -0800
Subject: [PATCH 14/16] fix

---
 compiler-rt/lib/scudo/standalone/combined.h | 30 ++++++++++-----------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index 2b72de0382b3102..458c69403240770 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -949,9 +949,8 @@ class Allocator {
 
   static const uptr MaxTraceSize = 64;
 
-  static void collectTraceMaybe(const char *RawStackDepot,
+  static void collectTraceMaybe(const StackDepot *Depot,
                                 uintptr_t (&Trace)[MaxTraceSize], u32 Hash) {
-    auto *Depot = reinterpret_cast<const StackDepot *>(RawStackDepot);
     uptr RingPos, Size;
     if (!Depot->find(Hash, &RingPos, &Size))
       return;
@@ -974,12 +973,14 @@ class Allocator {
         MemoryAddr + MemorySize < MemoryAddr)
       return;
 
+    const StackDepot *Depot = nullptr;
     if (DepotPtr) {
       // check for corrupted StackDepot. First we need to check whether we can
       // read the metadata, then whether the metadata matches the size.
-      if (DepotSize < sizeof(Depot))
+      if (DepotSize < sizeof(*Depot))
         return;
-      if (!reinterpret_cast<const StackDepot *>(DepotPtr)->isValid(DepotSize))
+      Depot = reinterpret_cast<const StackDepot *>(DepotPtr);
+      if (!Depot->isValid(DepotSize))
         return;
     }
 
@@ -988,19 +989,19 @@ class Allocator {
     // Check for OOB in the current block and the two surrounding blocks. Beyond
     // that, UAF is more likely.
     if (extractTag(FaultAddr) != 0)
-      getInlineErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, DepotPtr,
+      getInlineErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, Depot,
                          RegionInfoPtr, Memory, MemoryTags, MemoryAddr,
                          MemorySize, 0, 2);
 
     // Check the ring buffer. For primary allocations this will only find UAF;
     // for secondary allocations we can find either UAF or OOB.
-    getRingBufferErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, DepotPtr,
+    getRingBufferErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, Depot,
                            RingBufferPtr, RingBufferSize);
 
     // Check for OOB in the 28 blocks surrounding the 3 we checked earlier.
     // Beyond that we are likely to hit false positives.
     if (extractTag(FaultAddr) != 0)
-      getInlineErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, DepotPtr,
+      getInlineErrorInfo(ErrorInfo, NextErrorReport, FaultAddr, Depot,
                          RegionInfoPtr, Memory, MemoryTags, MemoryAddr,
                          MemorySize, 2, 16);
   }
@@ -1338,7 +1339,7 @@ class Allocator {
 
   static void getInlineErrorInfo(struct scudo_error_info *ErrorInfo,
                                  size_t &NextErrorReport, uintptr_t FaultAddr,
-                                 const char *RawStackDepot,
+                                 const StackDepot *Depot,
                                  const char *RegionInfoPtr, const char *Memory,
                                  const char *MemoryTags, uintptr_t MemoryAddr,
                                  size_t MemorySize, size_t MinDistance,
@@ -1403,8 +1404,8 @@ class Allocator {
           UntaggedFaultAddr < ChunkAddr ? BUFFER_UNDERFLOW : BUFFER_OVERFLOW;
       R->allocation_address = ChunkAddr;
       R->allocation_size = Header.SizeOrUnusedBytes;
-      if (RawStackDepot) {
-        collectTraceMaybe(RawStackDepot, R->allocation_trace,
+      if (Depot) {
+        collectTraceMaybe(Depot, R->allocation_trace,
                           Data[MemTagAllocationTraceIndex]);
       }
       R->allocation_tid = Data[MemTagAllocationTidIndex];
@@ -1423,13 +1424,13 @@ class Allocator {
   static void getRingBufferErrorInfo(struct scudo_error_info *ErrorInfo,
                                      size_t &NextErrorReport,
                                      uintptr_t FaultAddr,
-                                     const char *RawStackDepot,
+                                     const StackDepot *Depot,
                                      const char *RingBufferPtr,
                                      size_t RingBufferSize) {
     auto *RingBuffer =
         reinterpret_cast<const AllocationRingBuffer *>(RingBufferPtr);
     size_t RingBufferElements = ringBufferElementsFromBytes(RingBufferSize);
-    if (!RingBuffer || RingBufferElements == 0 || !RawStackDepot)
+    if (!RingBuffer || RingBufferElements == 0 || !Depot)
       return;
     uptr Pos = atomic_load_relaxed(&RingBuffer->Pos);
 
@@ -1488,10 +1489,9 @@ class Allocator {
 
       R->allocation_address = UntaggedEntryPtr;
       R->allocation_size = EntrySize;
-      collectTraceMaybe(RawStackDepot, R->allocation_trace, AllocationTrace);
+      collectTraceMaybe(Depot, R->allocation_trace, AllocationTrace);
       R->allocation_tid = AllocationTid;
-      collectTraceMaybe(RawStackDepot, R->deallocation_trace,
-                        DeallocationTrace);
+      collectTraceMaybe(Depot, R->deallocation_trace, DeallocationTrace);
       R->deallocation_tid = DeallocationTid;
     }
   }

>From 6245b90a2b73d520794d7f4ce6e249711f563a1a Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Tue, 23 Jan 2024 17:33:59 -0800
Subject: [PATCH 15/16] fmt

---
 compiler-rt/lib/scudo/standalone/combined.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index 458c69403240770..d06f003c1a3608b 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -291,8 +291,7 @@ class Allocator {
     uptr Size =
         android_unsafe_frame_pointer_chase(Stack, MaxTraceSize + DiscardFrames);
     Size = Min<uptr>(Size, MaxTraceSize + DiscardFrames);
-    return Depot->insert(Stack + Min<uptr>(DiscardFrames, Size),
-                         Stack + Size);
+    return Depot->insert(Stack + Min<uptr>(DiscardFrames, Size), Stack + Size);
 #else
     return 0;
 #endif

>From 4fc829753486d4f27cfa950ce6d8590dcad7f6a8 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Thu, 25 Jan 2024 12:08:33 -0800
Subject: [PATCH 16/16] depotcheck

---
 compiler-rt/lib/scudo/standalone/combined.h | 29 ++++++++++++---------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index d06f003c1a3608b..b3df273e5aaf244 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -283,7 +283,7 @@ class Allocator {
     return reinterpret_cast<void *>(addHeaderTag(reinterpret_cast<uptr>(Ptr)));
   }
 
-  NOINLINE u32 collectStackTrace() {
+  NOINLINE u32 collectStackTrace(StackDepot *Depot) {
 #ifdef HAVE_ANDROID_UNSAFE_FRAME_POINTER_CHASE
     // Discard collectStackTrace() frame and allocator function frame.
     constexpr uptr DiscardFrames = 2;
@@ -293,6 +293,7 @@ class Allocator {
     Size = Min<uptr>(Size, MaxTraceSize + DiscardFrames);
     return Depot->insert(Stack + Min<uptr>(DiscardFrames, Size), Stack + Size);
 #else
+    (void)(Depot);
     return 0;
 #endif
   }
@@ -1265,12 +1266,18 @@ class Allocator {
     storeEndMarker(RoundNewPtr, NewSize, BlockEnd);
   }
 
+  StackDepot *getDepotIfEnabled(const Options &Options) {
+    if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)))
+      return nullptr;
+    return Depot;
+  }
+
   void storePrimaryAllocationStackMaybe(const Options &Options, void *Ptr) {
-    if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)) ||
-        !RawRingBuffer)
+    auto *Depot = getDepotIfEnabled(Options);
+    if (!Depot)
       return;
     auto *Ptr32 = reinterpret_cast<u32 *>(Ptr);
-    Ptr32[MemTagAllocationTraceIndex] = collectStackTrace();
+    Ptr32[MemTagAllocationTraceIndex] = collectStackTrace(Depot);
     Ptr32[MemTagAllocationTidIndex] = getThreadID();
   }
 
@@ -1300,11 +1307,10 @@ class Allocator {
 
   void storeSecondaryAllocationStackMaybe(const Options &Options, void *Ptr,
                                           uptr Size) {
-    if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)) ||
-        !RawRingBuffer)
+    auto *Depot = getDepotIfEnabled(Options);
+    if (!Depot)
       return;
-
-    u32 Trace = collectStackTrace();
+    u32 Trace = collectStackTrace(Depot);
     u32 Tid = getThreadID();
 
     auto *Ptr32 = reinterpret_cast<u32 *>(Ptr);
@@ -1316,15 +1322,14 @@ class Allocator {
 
   void storeDeallocationStackMaybe(const Options &Options, void *Ptr,
                                    u8 PrevTag, uptr Size) {
-    if (!UNLIKELY(Options.get(OptionBit::TrackAllocationStacks)) ||
-        !RawRingBuffer)
+    auto *Depot = getDepotIfEnabled(Options);
+    if (!Depot)
       return;
-
     auto *Ptr32 = reinterpret_cast<u32 *>(Ptr);
     u32 AllocationTrace = Ptr32[MemTagAllocationTraceIndex];
     u32 AllocationTid = Ptr32[MemTagAllocationTidIndex];
 
-    u32 DeallocationTrace = collectStackTrace();
+    u32 DeallocationTrace = collectStackTrace(Depot);
     u32 DeallocationTid = getThreadID();
 
     storeRingBufferEntry(addFixedTag(untagPointer(Ptr), PrevTag),



More information about the llvm-commits mailing list