[compiler-rt] [scudo] Add primary option to zero block on dealloc. (PR #142394)

via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 3 21:57:52 PDT 2025


================
@@ -296,6 +319,54 @@ TEST(ScudoPrimaryTest, Primary64OOM) {
   Allocator.unmapTestOnly();
 }
 
+TEST(ScudoPrimaryTest, ZeroOnDeallocFlagLimit) {
+  for (scudo::s32 flag_value :
+       {INT_MAX, INT_MAX - 1, 1 << 12, 1 << 10,
+        static_cast<scudo::s32>(
+            scudo::DefaultSizeClassMap::getSizeByClassId(6)),
+        static_cast<scudo::s32>(
+            scudo::DefaultSizeClassMap::getSizeByClassId(6) - 1)}) {
+    // Override the flag value.
+    scudo::getFlags()->zero_on_dealloc_max_size = flag_value;
+    // INT_MAX flag_value stands for unset, then the static parameter is used.
+    const scudo::uptr threshold =
+        flag_value == INT_MAX ? TestConfig6<scudo::DefaultSizeClassMap>::
+                                    Primary::DefaultZeroOnDeallocMaxSize
+                              : static_cast<scudo::uptr>(flag_value);
+
+    using Primary = TestAllocator<TestConfig6, scudo::DefaultSizeClassMap>;
+    Primary Allocator;
+    Allocator.init(/*ReleaseToOsInterval=*/-1);
+    typename Primary::SizeClassAllocatorT SizeClassAllocator;
+    scudo::GlobalStats Stats;
+    Stats.init();
+    SizeClassAllocator.init(&Stats, &Allocator);
+    for (scudo::uptr ClassId = 1;
+         ClassId < Primary::SizeClassMap::LargestClassId; ClassId++) {
+      void *Ptr = SizeClassAllocator.allocate(ClassId);
+      EXPECT_NE(Ptr, nullptr);
+      const scudo::uptr Size = Primary::getSizeByClassId(ClassId);
+      memset(Ptr, 'B', Size);
+
+      SizeClassAllocator.deallocate(ClassId, Ptr);
+      if (Size <= threshold) {
+        // Verify the block is full of zeros.
+        for (scudo::uptr I = 1; I < Size; ++I) {
+          ASSERT_TRUE(static_cast<char *>(Ptr)[I] == 0);
+        }
+      } else {
+        // Verify the block is full of data.
+        for (scudo::uptr I = 1; I < Size; ++I) {
+          ASSERT_TRUE(static_cast<char *>(Ptr)[I] != 0);
+        }
+      }
+    }
----------------
ChiaHungDuan wrote:

It accesses the memory after deallocation which makes me feel wrong. Currently, the simplest way in my mind is to have something like `verifyAllBlocksAreReleasedTestOnly` in primary allocator. Such as `verifyAllBlocksAreZeroedTestOnly` (and we have to implement it in both primary and secondary allocators.)

Or the alternative is to add a hook in `pushBlocks` (in primary) and `deallocate` (in secondary) to do something like
```
void pushBlocks(...) {
  if (verifyOnTestOnly) {
    if (EnableZeroOnDealloc) {
      ...
     }
   }
```
   
   
     

https://github.com/llvm/llvm-project/pull/142394


More information about the llvm-commits mailing list