@@ -80,6 +80,19 @@ struct TestNoCacheConfig {
8080 };
8181};
8282
83+ struct TestNoCacheNoGuardPageConfig {
84+ static const bool MaySupportMemoryTagging = false ;
85+ template <typename > using TSDRegistryT = void ;
86+ template <typename > using PrimaryT = void ;
87+ template <typename Config> using SecondaryT = scudo::MapAllocator<Config>;
88+
89+ struct Secondary {
90+ template <typename Config>
91+ using CacheT = scudo::MapAllocatorNoCache<Config>;
92+ static const bool EnableGuardPages = false ;
93+ };
94+ };
95+
8396struct TestCacheConfig {
8497 static const bool MaySupportMemoryTagging = false ;
8598 template <typename > using TSDRegistryT = void ;
@@ -100,6 +113,27 @@ struct TestCacheConfig {
100113 };
101114};
102115
116+ struct TestCacheNoGuardPageConfig {
117+ static const bool MaySupportMemoryTagging = false ;
118+ template <typename > using TSDRegistryT = void ;
119+ template <typename > using PrimaryT = void ;
120+ template <typename > using SecondaryT = void ;
121+
122+ struct Secondary {
123+ struct Cache {
124+ static const scudo::u32 EntriesArraySize = 128U ;
125+ static const scudo::u32 QuarantineSize = 0U ;
126+ static const scudo::u32 DefaultMaxEntriesCount = 64U ;
127+ static const scudo::uptr DefaultMaxEntrySize = 1UL << 20 ;
128+ static const scudo::s32 MinReleaseToOsIntervalMs = INT32_MIN;
129+ static const scudo::s32 MaxReleaseToOsIntervalMs = INT32_MAX;
130+ };
131+
132+ template <typename Config> using CacheT = scudo::MapAllocatorCache<Config>;
133+ static const bool EnableGuardPages = false ;
134+ };
135+ };
136+
103137template <typename Config> static void testBasic () {
104138 using SecondaryT = scudo::MapAllocator<scudo::SecondaryConfig<Config>>;
105139 AllocatorInfoType<Config> Info;
@@ -146,15 +180,17 @@ template <typename Config> static void testBasic() {
146180
147181TEST (ScudoSecondaryTest, Basic) {
148182 testBasic<TestNoCacheConfig>();
183+ testBasic<TestNoCacheNoGuardPageConfig>();
149184 testBasic<TestCacheConfig>();
185+ testBasic<TestCacheNoGuardPageConfig>();
150186 testBasic<scudo::DefaultConfig>();
151187}
152188
153189// This exercises a variety of combinations of size and alignment for the
154190// MapAllocator. The size computation done here mimic the ones done by the
155191// combined allocator.
156- TEST (ScudoSecondaryTest, AllocatorCombinations ) {
157- AllocatorInfoType<TestNoCacheConfig > Info;
192+ template < typename Config> void testAllocatorCombinations ( ) {
193+ AllocatorInfoType<Config > Info;
158194
159195 constexpr scudo::uptr MinAlign = FIRST_32_SECOND_64 (8 , 16 );
160196 constexpr scudo::uptr HeaderSize = scudo::roundUp (8 , MinAlign);
@@ -180,8 +216,13 @@ TEST(ScudoSecondaryTest, AllocatorCombinations) {
180216 }
181217}
182218
183- TEST (ScudoSecondaryTest, AllocatorIterate) {
184- AllocatorInfoType<TestNoCacheConfig> Info;
219+ TEST (ScudoSecondaryTest, AllocatorCombinations) {
220+ testAllocatorCombinations<TestNoCacheConfig>();
221+ testAllocatorCombinations<TestNoCacheNoGuardPageConfig>();
222+ }
223+
224+ template <typename Config> void testAllocatorIterate () {
225+ AllocatorInfoType<Config> Info;
185226
186227 std::vector<void *> V;
187228 for (scudo::uptr I = 0 ; I < 32U ; I++)
@@ -201,8 +242,13 @@ TEST(ScudoSecondaryTest, AllocatorIterate) {
201242 }
202243}
203244
204- TEST (ScudoSecondaryTest, AllocatorWithReleaseThreadsRace) {
205- AllocatorInfoType<TestNoCacheConfig> Info (/* ReleaseToOsInterval=*/ 0 );
245+ TEST (ScudoSecondaryTest, AllocatorIterate) {
246+ testAllocatorIterate<TestNoCacheConfig>();
247+ testAllocatorIterate<TestNoCacheNoGuardPageConfig>();
248+ }
249+
250+ template <typename Config> void testAllocatorWithReleaseThreadsRace () {
251+ AllocatorInfoType<Config> Info (/* ReleaseToOsInterval=*/ 0 );
206252
207253 std::mutex Mutex;
208254 std::condition_variable Cv;
@@ -243,6 +289,64 @@ TEST(ScudoSecondaryTest, AllocatorWithReleaseThreadsRace) {
243289 T.join ();
244290}
245291
292+ TEST (ScudoSecondaryTest, AllocatorWithReleaseThreadsRace) {
293+ testAllocatorWithReleaseThreadsRace<TestNoCacheConfig>();
294+ testAllocatorWithReleaseThreadsRace<TestNoCacheNoGuardPageConfig>();
295+ }
296+
297+ template <typename Config>
298+ void testGetMappedSize (scudo::uptr Size, scudo::uptr *mapped,
299+ scudo::uptr *guard_page_size) {
300+ AllocatorInfoType<Config> Info;
301+
302+ scudo::uptr Stats[scudo::StatCount] = {};
303+ Info.GlobalStats .get (Stats);
304+ *mapped = Stats[scudo::StatMapped];
305+ Stats[scudo::StatMapped] = 0 ;
306+
307+ // Make sure the allocation is aligned to a page boundary so that the checks
308+ // in the tests can avoid problems due to allocations having different
309+ // alignments.
310+ void *Ptr = Info.Allocator ->allocate (Info.Options , Size, PageSize);
311+ EXPECT_NE (Ptr, nullptr );
312+
313+ Info.GlobalStats .get (Stats);
314+ EXPECT_GE (Stats[scudo::StatMapped], *mapped);
315+ *mapped = Stats[scudo::StatMapped] - *mapped;
316+
317+ Info.Allocator ->deallocate (Info.Options , Ptr);
318+
319+ *guard_page_size = Info.Allocator ->getGuardPageSize ();
320+ }
321+
322+ TEST (ScudoSecondaryTest, VerifyGuardPageOption) {
323+ static scudo::uptr AllocSize = 1000 * PageSize;
324+
325+ // Verify that a config with guard pages enabled:
326+ // - Non-zero sized guard page
327+ // - Mapped in at least the size of the allocation plus 2 * guard page size
328+ scudo::uptr guard_mapped = 0 ;
329+ scudo::uptr guard_page_size = 0 ;
330+ testGetMappedSize<TestNoCacheConfig>(AllocSize, &guard_mapped,
331+ &guard_page_size);
332+ EXPECT_GT (guard_page_size, 0U );
333+ EXPECT_GE (guard_mapped, AllocSize + 2 * guard_page_size);
334+
335+ // Verify that a config with guard pages disabled:
336+ // - Zero sized guard page
337+ // - The total mapped in is greater than the allocation size
338+ scudo::uptr no_guard_mapped = 0 ;
339+ scudo::uptr no_guard_page_size = 0 ;
340+ testGetMappedSize<TestNoCacheNoGuardPageConfig>(AllocSize, &no_guard_mapped,
341+ &no_guard_page_size);
342+ EXPECT_EQ (no_guard_page_size, 0U );
343+ EXPECT_GE (no_guard_mapped, AllocSize);
344+
345+ // Verify that a guard page config mapped in at least twice the size of
346+ // their guard page when compared to a no guard page config.
347+ EXPECT_GE (guard_mapped, no_guard_mapped + guard_page_size * 2 );
348+ }
349+
246350// Value written to cache entries that are unmapped.
247351static scudo::u32 UnmappedMarker = 0xDEADBEEF ;
248352
0 commit comments