diff --git a/tcmalloc/internal/system_allocator.h b/tcmalloc/internal/system_allocator.h index fd344b2cd..7d92a94ee 100644 --- a/tcmalloc/internal/system_allocator.h +++ b/tcmalloc/internal/system_allocator.h @@ -582,6 +582,17 @@ void* SystemAllocator::MmapAlignedLocked( size_t size, size_t alignment, const MemoryTag tag) { using system_allocator_internal::MapFixedNoReplaceFlagAvailable; + constexpr uintptr_t kTagFree = uintptr_t{1} << kTagShift; + // Each memory tag partition spans kTagFree bytes (whereas kTagMask is the + // multi-bit mask across all tags), so requests with size or alignment larger + // than kTagFree would cross tag boundaries or clear tag bits in + // RandomMmapHint. + // TODO(b/141325493): Support allocations and alignments larger than kTagFree. + if (size == 0 || size > kTagFree || alignment == 0 || alignment > kTagFree || + !absl::has_single_bit(alignment)) { + return nullptr; + } + TC_ASSERT_LE(size, kTagMask); TC_ASSERT_LE(alignment, kTagMask); diff --git a/tcmalloc/internal/system_allocator_test.cc b/tcmalloc/internal/system_allocator_test.cc index 7c92d091f..e65056a0f 100644 --- a/tcmalloc/internal/system_allocator_test.cc +++ b/tcmalloc/internal/system_allocator_test.cc @@ -182,6 +182,22 @@ TEST(SystemAllocatorTest, SetAnonVmaNameHandlesEmptyAndSubstringViews) { } } +TEST(SystemAllocatorTest, MmapAlignedRejectsOutOfPartitionSizeAndAlignment) { + constexpr size_t kMinMmapAlloc = 1 << 30; + NumaTopology<2> topology; + topology.Init(); + SystemAllocator, 1> allocator(topology, kMinMmapAlloc); + + const size_t kPageSize = GetPageSize(); + constexpr size_t kPartitionSize = uintptr_t{1} << kTagShift; + EXPECT_EQ(allocator.MmapAligned(kPageSize, 2 * kPartitionSize, + MemoryTag::kSampledOrCold), + nullptr); + EXPECT_EQ(allocator.MmapAligned(kPartitionSize + kPageSize, kPageSize, + MemoryTag::kNormal), + nullptr); +} + } // namespace } // namespace tcmalloc_internal } // namespace tcmalloc