[compiler-rt] ef84e19 - [compiler-rt][memprof] fix off-by-one in shadow access-count accumula… (#208376)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 9 09:20:00 PDT 2026


Author: David CARLIER
Date: 2026-07-09T17:19:54+01:00
New Revision: ef84e19e3fd3f13ffbc87544054e6605226dfc79

URL: https://github.com/llvm/llvm-project/commit/ef84e19e3fd3f13ffbc87544054e6605226dfc79
DIFF: https://github.com/llvm/llvm-project/commit/ef84e19e3fd3f13ffbc87544054e6605226dfc79.diff

LOG: [compiler-rt][memprof] fix off-by-one in shadow access-count accumula… (#208376)

…tion.

GetShadowCount and GetShadowCountHistogram used an inclusive loop up to
MEM_TO_SHADOW(p + size), summing an extra adjacent cell when p + size is
granule-aligned. Use p + size - 1 to stay within the allocation.

Added: 
    compiler-rt/lib/memprof/tests/shadow.cpp

Modified: 
    compiler-rt/lib/memprof/memprof_allocator.cpp
    compiler-rt/lib/memprof/memprof_mapping.h
    compiler-rt/lib/memprof/tests/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/memprof/memprof_allocator.cpp b/compiler-rt/lib/memprof/memprof_allocator.cpp
index 60f5c853f9d76..d11a909a02c5e 100644
--- a/compiler-rt/lib/memprof/memprof_allocator.cpp
+++ b/compiler-rt/lib/memprof/memprof_allocator.cpp
@@ -218,27 +218,6 @@ AllocatorCache *GetAllocatorCache(MemprofThreadLocalMallocStorage *ms) {
   return &ms->allocator_cache;
 }
 
-// Accumulates the access count from the shadow for the given pointer and size.
-u64 GetShadowCount(uptr p, u32 size) {
-  u64 *shadow = (u64 *)MEM_TO_SHADOW(p);
-  u64 *shadow_end = (u64 *)MEM_TO_SHADOW(p + size);
-  u64 count = 0;
-  for (; shadow <= shadow_end; shadow++)
-    count += *shadow;
-  return count;
-}
-
-// Accumulates the access count from the shadow for the given pointer and size.
-// See memprof_mapping.h for an overview on histogram counters.
-u64 GetShadowCountHistogram(uptr p, u32 size) {
-  u8 *shadow = (u8 *)HISTOGRAM_MEM_TO_SHADOW(p);
-  u8 *shadow_end = (u8 *)HISTOGRAM_MEM_TO_SHADOW(p + size);
-  u64 count = 0;
-  for (; shadow <= shadow_end; shadow++)
-    count += *shadow;
-  return count;
-}
-
 // Clears the shadow counters (when memory is allocated).
 void ClearShadow(uptr addr, uptr size) {
   CHECK(AddrIsAlignedByGranularity(addr));

diff  --git a/compiler-rt/lib/memprof/memprof_mapping.h b/compiler-rt/lib/memprof/memprof_mapping.h
index 6da385ab3d6e2..b0d6b61caf2b5 100644
--- a/compiler-rt/lib/memprof/memprof_mapping.h
+++ b/compiler-rt/lib/memprof/memprof_mapping.h
@@ -128,6 +128,27 @@ inline bool AddrIsAlignedByGranularity(uptr a) {
   return (a & (SHADOW_GRANULARITY - 1)) == 0;
 }
 
+// Accumulates the access count from the shadow for the given pointer and size.
+inline u64 GetShadowCount(uptr p, u32 size) {
+  u64 *shadow = (u64 *)MEM_TO_SHADOW(p);
+  u64 *shadow_end = (u64 *)MEM_TO_SHADOW(p + size - 1);
+  u64 count = 0;
+  for (; shadow <= shadow_end; shadow++)
+    count += *shadow;
+  return count;
+}
+
+// Accumulates the access count from the shadow for the given pointer and size.
+// See the histogram overview above for the counter layout.
+inline u64 GetShadowCountHistogram(uptr p, u32 size) {
+  u8 *shadow = (u8 *)HISTOGRAM_MEM_TO_SHADOW(p);
+  u8 *shadow_end = (u8 *)HISTOGRAM_MEM_TO_SHADOW(p + size - 1);
+  u64 count = 0;
+  for (; shadow <= shadow_end; shadow++)
+    count += *shadow;
+  return count;
+}
+
 inline void RecordAccess(uptr a) {
   // If we use a 
diff erent shadow size then the type below needs adjustment.
   CHECK_EQ(SHADOW_ENTRY_SIZE, 8);

diff  --git a/compiler-rt/lib/memprof/tests/CMakeLists.txt b/compiler-rt/lib/memprof/tests/CMakeLists.txt
index 1603d47d019ed..282e3701ee732 100644
--- a/compiler-rt/lib/memprof/tests/CMakeLists.txt
+++ b/compiler-rt/lib/memprof/tests/CMakeLists.txt
@@ -28,6 +28,7 @@ set(MEMPROF_SOURCES
 set(MEMPROF_UNITTESTS
   histogram_encoding.cpp
   rawprofile.cpp
+  shadow.cpp
   driver.cpp)
 
 include_directories(../../../include)

diff  --git a/compiler-rt/lib/memprof/tests/shadow.cpp b/compiler-rt/lib/memprof/tests/shadow.cpp
new file mode 100644
index 0000000000000..28231914db551
--- /dev/null
+++ b/compiler-rt/lib/memprof/tests/shadow.cpp
@@ -0,0 +1,51 @@
+//===-- shadow.cpp --------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "memprof/memprof_mapping.h"
+
+#include "gtest/gtest.h"
+
+// The shadow-mapping macros read this global, which the full runtime normally
+// initializes. Provide a definition so the mapping lands in the fake shadow
+// below.
+extern "C" {
+__sanitizer::uptr __memprof_shadow_memory_dynamic_address;
+}
+
+namespace __memprof {
+namespace {
+
+// A granule-aligned fake "application" address.
+static const uptr kFakeMem = 0x40000000;
+
+// Point the shadow so that MEM_TO_SHADOW(kFakeMem) == &Shadow[0].
+static void MapShadow(void *Shadow) {
+  __memprof_shadow_memory_dynamic_address =
+      reinterpret_cast<uptr>(Shadow) - (kFakeMem >> SHADOW_SCALE);
+}
+
+TEST(MemprofShadowCount, ExcludesCellPastGranuleAlignedEnd) {
+  // [0],[1] cover the 128-byte (two 64B-granule) allocation; [2] is the
+  // adjacent block's counter and must NOT be summed.
+  alignas(8) u64 Shadow[3] = {10, 20, 999};
+  MapShadow(Shadow);
+  // 128 is a multiple of MEM_GRANULARITY (64) and kFakeMem is aligned, so
+  // p + size lands exactly on the next granule boundary.
+  EXPECT_EQ(GetShadowCount(kFakeMem, 128), 30u);
+}
+
+TEST(MemprofShadowCount, HistogramExcludesCellPastGranuleAlignedEnd) {
+  // [0],[1] cover the 16-byte (two 8B-granule) allocation; [2] is adjacent.
+  alignas(8) u8 Shadow[3] = {5, 7, 200};
+  MapShadow(Shadow);
+  // 16 is a multiple of HISTOGRAM_GRANULARITY (8).
+  EXPECT_EQ(GetShadowCountHistogram(kFakeMem, 16), 12u);
+}
+
+} // namespace
+} // namespace __memprof


        


More information about the llvm-commits mailing list