[compiler-rt] ed0fd13 - [scudo] Double frees result in chunk state error (#110345)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 15 17:14:53 PDT 2024
Author: Christopher Ferris
Date: 2024-10-15T17:14:50-07:00
New Revision: ed0fd13783a68af6033b2c489eb830af0726856c
URL: https://github.com/llvm/llvm-project/commit/ed0fd13783a68af6033b2c489eb830af0726856c
DIFF: https://github.com/llvm/llvm-project/commit/ed0fd13783a68af6033b2c489eb830af0726856c.diff
LOG: [scudo] Double frees result in chunk state error (#110345)
Fixes bug where a device that supports tagged pointers doesn't use
the tagged pointer when computing the checksum.
Add tests to verify that double frees result in chunk state error
not corrupted header errors.
Added:
Modified:
compiler-rt/lib/scudo/standalone/combined.h
compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index 323a8b9d76c994..5deb8c97f1c86e 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -1255,22 +1255,26 @@ class Allocator {
else
Header->State = Chunk::State::Quarantined;
- void *BlockBegin;
- if (LIKELY(!useMemoryTagging<AllocatorConfig>(Options))) {
+ if (LIKELY(!useMemoryTagging<AllocatorConfig>(Options)))
Header->OriginOrWasZeroed = 0U;
- if (BypassQuarantine && allocatorSupportsMemoryTagging<AllocatorConfig>())
- Ptr = untagPointer(Ptr);
- BlockBegin = getBlockBegin(Ptr, Header);
- } else {
+ else {
Header->OriginOrWasZeroed =
Header->ClassId && !TSDRegistry.getDisableMemInit();
- BlockBegin =
- retagBlock(Options, TaggedPtr, Ptr, Header, Size, BypassQuarantine);
}
Chunk::storeHeader(Cookie, Ptr, Header);
if (BypassQuarantine) {
+ void *BlockBegin;
+ if (LIKELY(!useMemoryTagging<AllocatorConfig>(Options))) {
+ // Must do this after storeHeader because loadHeader uses a tagged ptr.
+ if (allocatorSupportsMemoryTagging<AllocatorConfig>())
+ Ptr = untagPointer(Ptr);
+ BlockBegin = getBlockBegin(Ptr, Header);
+ } else {
+ BlockBegin = retagBlock(Options, TaggedPtr, Ptr, Header, Size, true);
+ }
+
const uptr ClassId = Header->ClassId;
if (LIKELY(ClassId)) {
bool CacheDrained;
@@ -1288,6 +1292,8 @@ class Allocator {
Secondary.deallocate(Options, BlockBegin);
}
} else {
+ if (UNLIKELY(useMemoryTagging<AllocatorConfig>(Options)))
+ retagBlock(Options, TaggedPtr, Ptr, Header, Size, false);
typename TSDRegistryT::ScopedTSD TSD(TSDRegistry);
Quarantine.put(&TSD->getQuarantineCache(),
QuarantineCallback(*this, TSD->getCache()), Ptr, Size);
diff --git a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
index 16b19e807e11bc..ff98eb3397ee0e 100644
--- a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
@@ -534,6 +534,27 @@ SCUDO_TYPED_TEST(ScudoCombinedDeathTest, UseAfterFree) {
}
}
+SCUDO_TYPED_TEST(ScudoCombinedDeathTest, DoubleFreeFromPrimary) {
+ auto *Allocator = this->Allocator.get();
+
+ for (scudo::uptr SizeLog = 0U; SizeLog <= 20U; SizeLog++) {
+ const scudo::uptr Size = 1U << SizeLog;
+ if (!isPrimaryAllocation<TestAllocator<TypeParam>>(Size, 0))
+ break;
+
+ // Verify that a double free results in a chunk state error.
+ EXPECT_DEATH(
+ {
+ // Allocate from primary
+ void *P = Allocator->allocate(Size, Origin);
+ ASSERT_TRUE(P != nullptr);
+ Allocator->deallocate(P, Origin);
+ Allocator->deallocate(P, Origin);
+ },
+ "invalid chunk state");
+ }
+}
+
SCUDO_TYPED_TEST(ScudoCombinedDeathTest, DisableMemoryTagging) {
auto *Allocator = this->Allocator.get();
More information about the llvm-commits
mailing list