@@ -80,6 +80,19 @@ struct TestNoCacheConfig {
80
80
};
81
81
};
82
82
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
+
83
96
struct TestCacheConfig {
84
97
static const bool MaySupportMemoryTagging = false ;
85
98
template <typename > using TSDRegistryT = void ;
@@ -100,6 +113,27 @@ struct TestCacheConfig {
100
113
};
101
114
};
102
115
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
+
103
137
template <typename Config> static void testBasic () {
104
138
using SecondaryT = scudo::MapAllocator<scudo::SecondaryConfig<Config>>;
105
139
AllocatorInfoType<Config> Info;
@@ -146,15 +180,17 @@ template <typename Config> static void testBasic() {
146
180
147
181
TEST (ScudoSecondaryTest, Basic) {
148
182
testBasic<TestNoCacheConfig>();
183
+ testBasic<TestNoCacheNoGuardPageConfig>();
149
184
testBasic<TestCacheConfig>();
185
+ testBasic<TestCacheNoGuardPageConfig>();
150
186
testBasic<scudo::DefaultConfig>();
151
187
}
152
188
153
189
// This exercises a variety of combinations of size and alignment for the
154
190
// MapAllocator. The size computation done here mimic the ones done by the
155
191
// combined allocator.
156
- TEST (ScudoSecondaryTest, AllocatorCombinations ) {
157
- AllocatorInfoType<TestNoCacheConfig > Info;
192
+ template < typename Config> void testAllocatorCombinations ( ) {
193
+ AllocatorInfoType<Config > Info;
158
194
159
195
constexpr scudo::uptr MinAlign = FIRST_32_SECOND_64 (8 , 16 );
160
196
constexpr scudo::uptr HeaderSize = scudo::roundUp (8 , MinAlign);
@@ -180,8 +216,13 @@ TEST(ScudoSecondaryTest, AllocatorCombinations) {
180
216
}
181
217
}
182
218
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;
185
226
186
227
std::vector<void *> V;
187
228
for (scudo::uptr I = 0 ; I < 32U ; I++)
@@ -201,8 +242,13 @@ TEST(ScudoSecondaryTest, AllocatorIterate) {
201
242
}
202
243
}
203
244
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 );
206
252
207
253
std::mutex Mutex;
208
254
std::condition_variable Cv;
@@ -243,6 +289,64 @@ TEST(ScudoSecondaryTest, AllocatorWithReleaseThreadsRace) {
243
289
T.join ();
244
290
}
245
291
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
+
246
350
// Value written to cache entries that are unmapped.
247
351
static scudo::u32 UnmappedMarker = 0xDEADBEEF ;
248
352
0 commit comments