aboutsummaryrefslogtreecommitdiff
path: root/compiler-rt/lib/scudo/standalone/combined.h
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib/scudo/standalone/combined.h')
-rw-r--r--compiler-rt/lib/scudo/standalone/combined.h88
1 files changed, 71 insertions, 17 deletions
diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index 329ec45..ffe9554 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -706,19 +706,26 @@ public:
if (!getChunkFromBlock(Block, &Chunk, &Header) &&
!getChunkFromBlock(addHeaderTag(Block), &Chunk, &Header))
return;
- } else {
- if (!getChunkFromBlock(addHeaderTag(Block), &Chunk, &Header))
- return;
+ } else if (!getChunkFromBlock(addHeaderTag(Block), &Chunk, &Header)) {
+ return;
}
- if (Header.State == Chunk::State::Allocated) {
- uptr TaggedChunk = Chunk;
- if (allocatorSupportsMemoryTagging<AllocatorConfig>())
- TaggedChunk = untagPointer(TaggedChunk);
- if (useMemoryTagging<AllocatorConfig>(Primary.Options.load()))
- TaggedChunk = loadTag(Chunk);
- Callback(TaggedChunk, getSize(reinterpret_cast<void *>(Chunk), &Header),
- Arg);
+
+ if (Header.State != Chunk::State::Allocated)
+ return;
+
+ uptr TaggedChunk = Chunk;
+ if (allocatorSupportsMemoryTagging<AllocatorConfig>())
+ TaggedChunk = untagPointer(TaggedChunk);
+ uptr Size;
+ if (UNLIKELY(useMemoryTagging<AllocatorConfig>(Primary.Options.load()))) {
+ TaggedChunk = loadTag(Chunk);
+ Size = getSize(reinterpret_cast<void *>(Chunk), &Header);
+ } else if (AllocatorConfig::getExactUsableSize()) {
+ Size = getSize(reinterpret_cast<void *>(Chunk), &Header);
+ } else {
+ Size = getUsableSize(reinterpret_cast<void *>(Chunk), &Header);
}
+ Callback(TaggedChunk, Size, Arg);
};
Primary.iterateOverBlocks(Lambda);
Secondary.iterateOverBlocks(Lambda);
@@ -759,16 +766,50 @@ public:
return false;
}
- // Return the usable size for a given chunk. Technically we lie, as we just
- // report the actual size of a chunk. This is done to counteract code actively
- // writing past the end of a chunk (like sqlite3) when the usable size allows
- // for it, which then forces realloc to copy the usable size of a chunk as
- // opposed to its actual size.
+ ALWAYS_INLINE uptr getUsableSize(const void *Ptr,
+ Chunk::UnpackedHeader *Header) {
+ void *BlockBegin = getBlockBegin(Ptr, Header);
+ if (LIKELY(Header->ClassId)) {
+ return SizeClassMap::getSizeByClassId(Header->ClassId) -
+ (reinterpret_cast<uptr>(Ptr) - reinterpret_cast<uptr>(BlockBegin));
+ }
+
+ uptr UntaggedPtr = reinterpret_cast<uptr>(Ptr);
+ if (allocatorSupportsMemoryTagging<AllocatorConfig>()) {
+ UntaggedPtr = untagPointer(UntaggedPtr);
+ BlockBegin = untagPointer(BlockBegin);
+ }
+ return SecondaryT::getBlockEnd(BlockBegin) - UntaggedPtr;
+ }
+
+ // Return the usable size for a given chunk. If MTE is enabled or if the
+ // ExactUsableSize config parameter is true, we report the exact size of
+ // the original allocation size. Otherwise, we will return the total
+ // actual usable size.
uptr getUsableSize(const void *Ptr) {
if (UNLIKELY(!Ptr))
return 0;
- return getAllocSize(Ptr);
+ if (AllocatorConfig::getExactUsableSize() ||
+ UNLIKELY(useMemoryTagging<AllocatorConfig>(Primary.Options.load())))
+ return getAllocSize(Ptr);
+
+ initThreadMaybe();
+
+#ifdef GWP_ASAN_HOOKS
+ if (UNLIKELY(GuardedAlloc.pointerIsMine(Ptr)))
+ return GuardedAlloc.getSize(Ptr);
+#endif // GWP_ASAN_HOOKS
+
+ Ptr = getHeaderTaggedPointer(const_cast<void *>(Ptr));
+ Chunk::UnpackedHeader Header;
+ Chunk::loadHeader(Cookie, Ptr, &Header);
+
+ // Getting the alloc size of a chunk only makes sense if it's allocated.
+ if (UNLIKELY(Header.State != Chunk::State::Allocated))
+ reportInvalidChunkState(AllocatorAction::Sizing, Ptr);
+
+ return getUsableSize(Ptr, &Header);
}
uptr getAllocSize(const void *Ptr) {
@@ -951,6 +992,19 @@ public:
MemorySize, 2, 16);
}
+ uptr getBlockBeginTestOnly(const void *Ptr) {
+ Chunk::UnpackedHeader Header;
+ Chunk::loadHeader(Cookie, Ptr, &Header);
+ DCHECK(Header.State == Chunk::State::Allocated);
+
+ if (allocatorSupportsMemoryTagging<AllocatorConfig>())
+ Ptr = untagPointer(const_cast<void *>(Ptr));
+ void *Begin = getBlockBegin(Ptr, &Header);
+ if (allocatorSupportsMemoryTagging<AllocatorConfig>())
+ Begin = untagPointer(Begin);
+ return reinterpret_cast<uptr>(Begin);
+ }
+
private:
typedef typename PrimaryT::SizeClassMap SizeClassMap;