xref: /llvm-project/compiler-rt/lib/asan/tests/asan_interface_test.cpp (revision 4b4437c084e2b8a2643e97e7aef125c438635a4d)
1b47455b5SNico Weber //===-- asan_interface_test.cpp -------------------------------------------===//
2b47455b5SNico Weber //
3b47455b5SNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b47455b5SNico Weber // See https://llvm.org/LICENSE.txt for license information.
5b47455b5SNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b47455b5SNico Weber //
7b47455b5SNico Weber //===----------------------------------------------------------------------===//
8b47455b5SNico Weber //
9b47455b5SNico Weber // This file is a part of AddressSanitizer, an address sanity checker.
10b47455b5SNico Weber //
11b47455b5SNico Weber //===----------------------------------------------------------------------===//
12b47455b5SNico Weber #include "asan_test_utils.h"
13b47455b5SNico Weber #include "sanitizer_common/sanitizer_internal_defs.h"
14b47455b5SNico Weber #include <sanitizer/allocator_interface.h>
15b47455b5SNico Weber #include <sanitizer/asan_interface.h>
16b47455b5SNico Weber #include <vector>
17b47455b5SNico Weber 
TEST(AddressSanitizerInterface,GetEstimatedAllocatedSize)18b47455b5SNico Weber TEST(AddressSanitizerInterface, GetEstimatedAllocatedSize) {
19b47455b5SNico Weber   EXPECT_EQ(0U, __sanitizer_get_estimated_allocated_size(0));
20b47455b5SNico Weber   const size_t sizes[] = { 1, 30, 1<<30 };
21b47455b5SNico Weber   for (size_t i = 0; i < 3; i++) {
22b47455b5SNico Weber     EXPECT_EQ(sizes[i], __sanitizer_get_estimated_allocated_size(sizes[i]));
23b47455b5SNico Weber   }
24b47455b5SNico Weber }
25b47455b5SNico Weber 
26b47455b5SNico Weber static const char* kGetAllocatedSizeErrorMsg =
27b47455b5SNico Weber   "attempting to call __sanitizer_get_allocated_size";
28b47455b5SNico Weber 
TEST(AddressSanitizerInterface,GetAllocatedSizeAndOwnershipTest)29b47455b5SNico Weber TEST(AddressSanitizerInterface, GetAllocatedSizeAndOwnershipTest) {
30b47455b5SNico Weber   const size_t kArraySize = 100;
31b47455b5SNico Weber   char *array = Ident((char*)malloc(kArraySize));
32b47455b5SNico Weber   int *int_ptr = Ident(new int);
33b47455b5SNico Weber 
34b47455b5SNico Weber   // Allocated memory is owned by allocator. Allocated size should be
35b47455b5SNico Weber   // equal to requested size.
36b47455b5SNico Weber   EXPECT_EQ(true, __sanitizer_get_ownership(array));
37b47455b5SNico Weber   EXPECT_EQ(kArraySize, __sanitizer_get_allocated_size(array));
38b47455b5SNico Weber   EXPECT_EQ(true, __sanitizer_get_ownership(int_ptr));
39b47455b5SNico Weber   EXPECT_EQ(sizeof(int), __sanitizer_get_allocated_size(int_ptr));
40b47455b5SNico Weber 
41b47455b5SNico Weber   // We cannot call GetAllocatedSize from the memory we didn't map,
42b47455b5SNico Weber   // and from the interior pointers (not returned by previous malloc).
43b47455b5SNico Weber   void *wild_addr = (void*)0x1;
44b47455b5SNico Weber   EXPECT_FALSE(__sanitizer_get_ownership(wild_addr));
45b47455b5SNico Weber   EXPECT_DEATH(__sanitizer_get_allocated_size(wild_addr),
46b47455b5SNico Weber                kGetAllocatedSizeErrorMsg);
47b47455b5SNico Weber   EXPECT_FALSE(__sanitizer_get_ownership(array + kArraySize / 2));
48b47455b5SNico Weber   EXPECT_DEATH(__sanitizer_get_allocated_size(array + kArraySize / 2),
49b47455b5SNico Weber                kGetAllocatedSizeErrorMsg);
50b47455b5SNico Weber 
51b47455b5SNico Weber   // NULL is not owned, but is a valid argument for
52b47455b5SNico Weber   // __sanitizer_get_allocated_size().
53b47455b5SNico Weber   EXPECT_FALSE(__sanitizer_get_ownership(NULL));
54b47455b5SNico Weber   EXPECT_EQ(0U, __sanitizer_get_allocated_size(NULL));
55b47455b5SNico Weber 
56b47455b5SNico Weber   // When memory is freed, it's not owned, and call to GetAllocatedSize
57b47455b5SNico Weber   // is forbidden.
58b47455b5SNico Weber   free(array);
59b47455b5SNico Weber   EXPECT_FALSE(__sanitizer_get_ownership(array));
60b47455b5SNico Weber   EXPECT_DEATH(__sanitizer_get_allocated_size(array),
61b47455b5SNico Weber                kGetAllocatedSizeErrorMsg);
62b47455b5SNico Weber   delete int_ptr;
63b47455b5SNico Weber 
64b47455b5SNico Weber   void *zero_alloc = Ident(malloc(0));
65b47455b5SNico Weber   if (zero_alloc != 0) {
66b47455b5SNico Weber     // If malloc(0) is not null, this pointer is owned and should have valid
67b47455b5SNico Weber     // allocated size.
68b47455b5SNico Weber     EXPECT_TRUE(__sanitizer_get_ownership(zero_alloc));
69b47455b5SNico Weber     // Allocated size is 0 or 1 depending on the allocator used.
70b47455b5SNico Weber     EXPECT_LT(__sanitizer_get_allocated_size(zero_alloc), 2U);
71b47455b5SNico Weber   }
72b47455b5SNico Weber   free(zero_alloc);
73b47455b5SNico Weber }
74b47455b5SNico Weber 
TEST(AddressSanitizerInterface,GetCurrentAllocatedBytesTest)75b47455b5SNico Weber TEST(AddressSanitizerInterface, GetCurrentAllocatedBytesTest) {
76b47455b5SNico Weber   size_t before_malloc, after_malloc, after_free;
77b47455b5SNico Weber   char *array;
78b47455b5SNico Weber   const size_t kMallocSize = 100;
79b47455b5SNico Weber   before_malloc = __sanitizer_get_current_allocated_bytes();
80b47455b5SNico Weber 
81b47455b5SNico Weber   array = Ident((char*)malloc(kMallocSize));
82b47455b5SNico Weber   after_malloc = __sanitizer_get_current_allocated_bytes();
83b47455b5SNico Weber   EXPECT_EQ(before_malloc + kMallocSize, after_malloc);
84b47455b5SNico Weber 
85b47455b5SNico Weber   free(array);
86b47455b5SNico Weber   after_free = __sanitizer_get_current_allocated_bytes();
87b47455b5SNico Weber   EXPECT_EQ(before_malloc, after_free);
88b47455b5SNico Weber }
89b47455b5SNico Weber 
TEST(AddressSanitizerInterface,GetHeapSizeTest)90b47455b5SNico Weber TEST(AddressSanitizerInterface, GetHeapSizeTest) {
91b47455b5SNico Weber   // ASan allocator does not keep huge chunks in free list, but unmaps them.
92b47455b5SNico Weber   // The chunk should be greater than the quarantine size,
93a1e7e401SKazuaki Ishizaki   // otherwise it will be stuck in quarantine instead of being unmapped.
94b47455b5SNico Weber   static const size_t kLargeMallocSize = (1 << 28) + 1;  // 256M
95b47455b5SNico Weber   free(Ident(malloc(kLargeMallocSize)));  // Drain quarantine.
96b47455b5SNico Weber   size_t old_heap_size = __sanitizer_get_heap_size();
97b47455b5SNico Weber   for (int i = 0; i < 3; i++) {
98b47455b5SNico Weber     // fprintf(stderr, "allocating %zu bytes:\n", kLargeMallocSize);
99b47455b5SNico Weber     free(Ident(malloc(kLargeMallocSize)));
100b47455b5SNico Weber     EXPECT_EQ(old_heap_size, __sanitizer_get_heap_size());
101b47455b5SNico Weber   }
102b47455b5SNico Weber }
103b47455b5SNico Weber 
104b47455b5SNico Weber #if !defined(__NetBSD__)
105b47455b5SNico Weber static const size_t kManyThreadsMallocSizes[] = {5, 1UL<<10, 1UL<<14, 357};
106b47455b5SNico Weber static const size_t kManyThreadsIterations = 250;
107b47455b5SNico Weber static const size_t kManyThreadsNumThreads =
108b47455b5SNico Weber   (SANITIZER_WORDSIZE == 32) ? 40 : 200;
109b47455b5SNico Weber 
ManyThreadsWithStatsWorker(void * arg)110b47455b5SNico Weber static void *ManyThreadsWithStatsWorker(void *arg) {
111b47455b5SNico Weber   (void)arg;
112b47455b5SNico Weber   for (size_t iter = 0; iter < kManyThreadsIterations; iter++) {
113b47455b5SNico Weber     for (size_t size_index = 0; size_index < 4; size_index++) {
114b47455b5SNico Weber       free(Ident(malloc(kManyThreadsMallocSizes[size_index])));
115b47455b5SNico Weber     }
116b47455b5SNico Weber   }
117b47455b5SNico Weber   // Just one large allocation.
118b47455b5SNico Weber   free(Ident(malloc(1 << 20)));
119b47455b5SNico Weber   return 0;
120b47455b5SNico Weber }
121b47455b5SNico Weber 
TEST(AddressSanitizerInterface,ManyThreadsWithStatsStressTest)122b47455b5SNico Weber TEST(AddressSanitizerInterface, ManyThreadsWithStatsStressTest) {
123b47455b5SNico Weber   size_t before_test, after_test, i;
124b47455b5SNico Weber   pthread_t threads[kManyThreadsNumThreads];
125b47455b5SNico Weber   before_test = __sanitizer_get_current_allocated_bytes();
126b47455b5SNico Weber   for (i = 0; i < kManyThreadsNumThreads; i++) {
127b47455b5SNico Weber     PTHREAD_CREATE(&threads[i], 0,
128b47455b5SNico Weber                    (void* (*)(void *x))ManyThreadsWithStatsWorker, (void*)i);
129b47455b5SNico Weber   }
130b47455b5SNico Weber   for (i = 0; i < kManyThreadsNumThreads; i++) {
131b47455b5SNico Weber     PTHREAD_JOIN(threads[i], 0);
132b47455b5SNico Weber   }
133b47455b5SNico Weber   after_test = __sanitizer_get_current_allocated_bytes();
134b47455b5SNico Weber   // ASan stats also reflect memory usage of internal ASan RTL structs,
135b47455b5SNico Weber   // so we can't check for equality here.
136b47455b5SNico Weber   EXPECT_LT(after_test, before_test + (1UL<<20));
137b47455b5SNico Weber }
138b47455b5SNico Weber #endif
139b47455b5SNico Weber 
DoDoubleFree()140b47455b5SNico Weber static void DoDoubleFree() {
141b47455b5SNico Weber   int *x = Ident(new int);
142b47455b5SNico Weber   delete Ident(x);
143b47455b5SNico Weber   delete Ident(x);
144b47455b5SNico Weber }
145b47455b5SNico Weber 
MyDeathCallback()146b47455b5SNico Weber static void MyDeathCallback() {
147b47455b5SNico Weber   fprintf(stderr, "MyDeathCallback\n");
148b47455b5SNico Weber   fflush(0);  // On Windows, stderr doesn't flush on crash.
149b47455b5SNico Weber }
150b47455b5SNico Weber 
TEST(AddressSanitizerInterface,DeathCallbackTest)151b47455b5SNico Weber TEST(AddressSanitizerInterface, DeathCallbackTest) {
152b47455b5SNico Weber   __asan_set_death_callback(MyDeathCallback);
153b47455b5SNico Weber   EXPECT_DEATH(DoDoubleFree(), "MyDeathCallback");
154b47455b5SNico Weber   __asan_set_death_callback(NULL);
155b47455b5SNico Weber }
156b47455b5SNico Weber 
157b47455b5SNico Weber #define GOOD_ACCESS(ptr, offset)  \
158b47455b5SNico Weber     EXPECT_FALSE(__asan_address_is_poisoned(ptr + offset))
159b47455b5SNico Weber 
160b47455b5SNico Weber #define BAD_ACCESS(ptr, offset) \
161b47455b5SNico Weber     EXPECT_TRUE(__asan_address_is_poisoned(ptr + offset))
162b47455b5SNico Weber 
163b47455b5SNico Weber static const char* kUseAfterPoisonErrorMessage = "use-after-poison";
164b47455b5SNico Weber 
TEST(AddressSanitizerInterface,SimplePoisonMemoryRegionTest)165b47455b5SNico Weber TEST(AddressSanitizerInterface, SimplePoisonMemoryRegionTest) {
166b47455b5SNico Weber   char *array = Ident((char*)malloc(120));
167b47455b5SNico Weber   // poison array[40..80)
168b47455b5SNico Weber   __asan_poison_memory_region(array + 40, 40);
169b47455b5SNico Weber   GOOD_ACCESS(array, 39);
170b47455b5SNico Weber   GOOD_ACCESS(array, 80);
171b47455b5SNico Weber   BAD_ACCESS(array, 40);
172b47455b5SNico Weber   BAD_ACCESS(array, 60);
173b47455b5SNico Weber   BAD_ACCESS(array, 79);
1743c47f5f4SVitaly Buka   EXPECT_DEATH(Ident(array[40]), kUseAfterPoisonErrorMessage);
175b47455b5SNico Weber   __asan_unpoison_memory_region(array + 40, 40);
176b47455b5SNico Weber   // access previously poisoned memory.
177b47455b5SNico Weber   GOOD_ACCESS(array, 40);
178b47455b5SNico Weber   GOOD_ACCESS(array, 79);
179b47455b5SNico Weber   free(array);
180b47455b5SNico Weber }
181b47455b5SNico Weber 
TEST(AddressSanitizerInterface,OverlappingPoisonMemoryRegionTest)182b47455b5SNico Weber TEST(AddressSanitizerInterface, OverlappingPoisonMemoryRegionTest) {
183b47455b5SNico Weber   char *array = Ident((char*)malloc(120));
184b47455b5SNico Weber   // Poison [0..40) and [80..120)
185b47455b5SNico Weber   __asan_poison_memory_region(array, 40);
186b47455b5SNico Weber   __asan_poison_memory_region(array + 80, 40);
187b47455b5SNico Weber   BAD_ACCESS(array, 20);
188b47455b5SNico Weber   GOOD_ACCESS(array, 60);
189b47455b5SNico Weber   BAD_ACCESS(array, 100);
190b47455b5SNico Weber   // Poison whole array - [0..120)
191b47455b5SNico Weber   __asan_poison_memory_region(array, 120);
192b47455b5SNico Weber   BAD_ACCESS(array, 60);
193b47455b5SNico Weber   // Unpoison [24..96)
194b47455b5SNico Weber   __asan_unpoison_memory_region(array + 24, 72);
195b47455b5SNico Weber   BAD_ACCESS(array, 23);
196b47455b5SNico Weber   GOOD_ACCESS(array, 24);
197b47455b5SNico Weber   GOOD_ACCESS(array, 60);
198b47455b5SNico Weber   GOOD_ACCESS(array, 95);
199b47455b5SNico Weber   BAD_ACCESS(array, 96);
200b47455b5SNico Weber   free(array);
201b47455b5SNico Weber }
202b47455b5SNico Weber 
TEST(AddressSanitizerInterface,PushAndPopWithPoisoningTest)203b47455b5SNico Weber TEST(AddressSanitizerInterface, PushAndPopWithPoisoningTest) {
204b47455b5SNico Weber   // Vector of capacity 20
205b47455b5SNico Weber   char *vec = Ident((char*)malloc(20));
206b47455b5SNico Weber   __asan_poison_memory_region(vec, 20);
207b47455b5SNico Weber   for (size_t i = 0; i < 7; i++) {
208b47455b5SNico Weber     // Simulate push_back.
209b47455b5SNico Weber     __asan_unpoison_memory_region(vec + i, 1);
210b47455b5SNico Weber     GOOD_ACCESS(vec, i);
211b47455b5SNico Weber     BAD_ACCESS(vec, i + 1);
212b47455b5SNico Weber   }
213b47455b5SNico Weber   for (size_t i = 7; i > 0; i--) {
214b47455b5SNico Weber     // Simulate pop_back.
215b47455b5SNico Weber     __asan_poison_memory_region(vec + i - 1, 1);
216b47455b5SNico Weber     BAD_ACCESS(vec, i - 1);
217b47455b5SNico Weber     if (i > 1) GOOD_ACCESS(vec, i - 2);
218b47455b5SNico Weber   }
219b47455b5SNico Weber   free(vec);
220b47455b5SNico Weber }
221b47455b5SNico Weber 
222b47455b5SNico Weber #if !defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3
223b47455b5SNico Weber // Make sure that each aligned block of size "2^granularity" doesn't have
224b47455b5SNico Weber // "true" value before "false" value.
MakeShadowValid(bool * shadow,int length,int granularity)225b47455b5SNico Weber static void MakeShadowValid(bool *shadow, int length, int granularity) {
226b47455b5SNico Weber   bool can_be_poisoned = true;
227b47455b5SNico Weber   for (int i = length - 1; i >= 0; i--) {
228b47455b5SNico Weber     if (!shadow[i])
229b47455b5SNico Weber       can_be_poisoned = false;
230b47455b5SNico Weber     if (!can_be_poisoned)
231b47455b5SNico Weber       shadow[i] = false;
232b47455b5SNico Weber     if (i % (1 << granularity) == 0) {
233b47455b5SNico Weber       can_be_poisoned = true;
234b47455b5SNico Weber     }
235b47455b5SNico Weber   }
236b47455b5SNico Weber }
237b47455b5SNico Weber 
TEST(AddressSanitizerInterface,PoisoningStressTest)238b47455b5SNico Weber TEST(AddressSanitizerInterface, PoisoningStressTest) {
239b47455b5SNico Weber   const size_t kSize = 24;
240b47455b5SNico Weber   bool expected[kSize];
241b47455b5SNico Weber   char *arr = Ident((char*)malloc(kSize));
242b47455b5SNico Weber   for (size_t l1 = 0; l1 < kSize; l1++) {
243b47455b5SNico Weber     for (size_t s1 = 1; l1 + s1 <= kSize; s1++) {
244b47455b5SNico Weber       for (size_t l2 = 0; l2 < kSize; l2++) {
245b47455b5SNico Weber         for (size_t s2 = 1; l2 + s2 <= kSize; s2++) {
246b47455b5SNico Weber           // Poison [l1, l1+s1), [l2, l2+s2) and check result.
247b47455b5SNico Weber           __asan_unpoison_memory_region(arr, kSize);
248b47455b5SNico Weber           __asan_poison_memory_region(arr + l1, s1);
249b47455b5SNico Weber           __asan_poison_memory_region(arr + l2, s2);
250b47455b5SNico Weber           memset(expected, false, kSize);
251b47455b5SNico Weber           memset(expected + l1, true, s1);
252b47455b5SNico Weber           MakeShadowValid(expected, kSize, /*granularity*/ 3);
253b47455b5SNico Weber           memset(expected + l2, true, s2);
254b47455b5SNico Weber           MakeShadowValid(expected, kSize, /*granularity*/ 3);
255b47455b5SNico Weber           for (size_t i = 0; i < kSize; i++) {
256b47455b5SNico Weber             ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));
257b47455b5SNico Weber           }
258b47455b5SNico Weber           // Unpoison [l1, l1+s1) and [l2, l2+s2) and check result.
259b47455b5SNico Weber           __asan_poison_memory_region(arr, kSize);
260b47455b5SNico Weber           __asan_unpoison_memory_region(arr + l1, s1);
261b47455b5SNico Weber           __asan_unpoison_memory_region(arr + l2, s2);
262b47455b5SNico Weber           memset(expected, true, kSize);
263b47455b5SNico Weber           memset(expected + l1, false, s1);
264b47455b5SNico Weber           MakeShadowValid(expected, kSize, /*granularity*/ 3);
265b47455b5SNico Weber           memset(expected + l2, false, s2);
266b47455b5SNico Weber           MakeShadowValid(expected, kSize, /*granularity*/ 3);
267b47455b5SNico Weber           for (size_t i = 0; i < kSize; i++) {
268b47455b5SNico Weber             ASSERT_EQ(expected[i], __asan_address_is_poisoned(arr + i));
269b47455b5SNico Weber           }
270b47455b5SNico Weber         }
271b47455b5SNico Weber       }
272b47455b5SNico Weber     }
273b47455b5SNico Weber   }
274b47455b5SNico Weber   free(arr);
275b47455b5SNico Weber }
276b47455b5SNico Weber #endif  // !defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3
277b47455b5SNico Weber 
TEST(AddressSanitizerInterface,GlobalRedzones)278b47455b5SNico Weber TEST(AddressSanitizerInterface, GlobalRedzones) {
279b47455b5SNico Weber   GOOD_ACCESS(glob1, 1 - 1);
280b47455b5SNico Weber   GOOD_ACCESS(glob2, 2 - 1);
281b47455b5SNico Weber   GOOD_ACCESS(glob3, 3 - 1);
282b47455b5SNico Weber   GOOD_ACCESS(glob4, 4 - 1);
283b47455b5SNico Weber   GOOD_ACCESS(glob5, 5 - 1);
284b47455b5SNico Weber   GOOD_ACCESS(glob6, 6 - 1);
285b47455b5SNico Weber   GOOD_ACCESS(glob7, 7 - 1);
286b47455b5SNico Weber   GOOD_ACCESS(glob8, 8 - 1);
287b47455b5SNico Weber   GOOD_ACCESS(glob9, 9 - 1);
288b47455b5SNico Weber   GOOD_ACCESS(glob10, 10 - 1);
289b47455b5SNico Weber   GOOD_ACCESS(glob11, 11 - 1);
290b47455b5SNico Weber   GOOD_ACCESS(glob12, 12 - 1);
291b47455b5SNico Weber   GOOD_ACCESS(glob13, 13 - 1);
292b47455b5SNico Weber   GOOD_ACCESS(glob14, 14 - 1);
293b47455b5SNico Weber   GOOD_ACCESS(glob15, 15 - 1);
294b47455b5SNico Weber   GOOD_ACCESS(glob16, 16 - 1);
295b47455b5SNico Weber   GOOD_ACCESS(glob17, 17 - 1);
296b47455b5SNico Weber   GOOD_ACCESS(glob1000, 1000 - 1);
297b47455b5SNico Weber   GOOD_ACCESS(glob10000, 10000 - 1);
298b47455b5SNico Weber   GOOD_ACCESS(glob100000, 100000 - 1);
299b47455b5SNico Weber 
300b47455b5SNico Weber   BAD_ACCESS(glob1, 1);
301b47455b5SNico Weber   BAD_ACCESS(glob2, 2);
302b47455b5SNico Weber   BAD_ACCESS(glob3, 3);
303b47455b5SNico Weber   BAD_ACCESS(glob4, 4);
304b47455b5SNico Weber   BAD_ACCESS(glob5, 5);
305b47455b5SNico Weber   BAD_ACCESS(glob6, 6);
306b47455b5SNico Weber   BAD_ACCESS(glob7, 7);
307b47455b5SNico Weber   BAD_ACCESS(glob8, 8);
308b47455b5SNico Weber   BAD_ACCESS(glob9, 9);
309b47455b5SNico Weber   BAD_ACCESS(glob10, 10);
310b47455b5SNico Weber   BAD_ACCESS(glob11, 11);
311b47455b5SNico Weber   BAD_ACCESS(glob12, 12);
312b47455b5SNico Weber   BAD_ACCESS(glob13, 13);
313b47455b5SNico Weber   BAD_ACCESS(glob14, 14);
314b47455b5SNico Weber   BAD_ACCESS(glob15, 15);
315b47455b5SNico Weber   BAD_ACCESS(glob16, 16);
316b47455b5SNico Weber   BAD_ACCESS(glob17, 17);
317b47455b5SNico Weber   BAD_ACCESS(glob1000, 1000);
318b47455b5SNico Weber   BAD_ACCESS(glob1000, 1100);  // Redzone is at least 101 bytes.
319b47455b5SNico Weber   BAD_ACCESS(glob10000, 10000);
320b47455b5SNico Weber   BAD_ACCESS(glob10000, 11000);  // Redzone is at least 1001 bytes.
321b47455b5SNico Weber   BAD_ACCESS(glob100000, 100000);
322b47455b5SNico Weber   BAD_ACCESS(glob100000, 110000);  // Redzone is at least 10001 bytes.
323b47455b5SNico Weber }
324b47455b5SNico Weber 
TEST(AddressSanitizerInterface,PoisonedRegion)325b47455b5SNico Weber TEST(AddressSanitizerInterface, PoisonedRegion) {
326b47455b5SNico Weber   size_t rz = 16;
327b47455b5SNico Weber   for (size_t size = 1; size <= 64; size++) {
328b47455b5SNico Weber     char *p = new char[size];
329b47455b5SNico Weber     for (size_t beg = 0; beg < size + rz; beg++) {
330b47455b5SNico Weber       for (size_t end = beg; end < size + rz; end++) {
331b47455b5SNico Weber         void *first_poisoned = __asan_region_is_poisoned(p + beg, end - beg);
332b47455b5SNico Weber         if (beg == end) {
333b47455b5SNico Weber           EXPECT_FALSE(first_poisoned);
334b47455b5SNico Weber         } else if (beg < size && end <= size) {
335b47455b5SNico Weber           EXPECT_FALSE(first_poisoned);
336b47455b5SNico Weber         } else if (beg >= size) {
337b47455b5SNico Weber           EXPECT_EQ(p + beg, first_poisoned);
338b47455b5SNico Weber         } else {
339b47455b5SNico Weber           EXPECT_GT(end, size);
340b47455b5SNico Weber           EXPECT_EQ(p + size, first_poisoned);
341b47455b5SNico Weber         }
342b47455b5SNico Weber       }
343b47455b5SNico Weber     }
344b47455b5SNico Weber     delete [] p;
345b47455b5SNico Weber   }
346b47455b5SNico Weber }
347b47455b5SNico Weber 
348b47455b5SNico Weber // This is a performance benchmark for manual runs.
349b47455b5SNico Weber // asan's memset interceptor calls mem_is_zero for the entire shadow region.
350b47455b5SNico Weber // the profile should look like this:
351b47455b5SNico Weber //     89.10%   [.] __memset_sse2
352b47455b5SNico Weber //     10.50%   [.] __sanitizer::mem_is_zero
353b47455b5SNico Weber // I.e. mem_is_zero should consume ~ SHADOW_GRANULARITY less CPU cycles
354b47455b5SNico Weber // than memset itself.
TEST(AddressSanitizerInterface,DISABLED_StressLargeMemset)355b47455b5SNico Weber TEST(AddressSanitizerInterface, DISABLED_StressLargeMemset) {
356b47455b5SNico Weber   size_t size = 1 << 20;
357b47455b5SNico Weber   char *x = new char[size];
358b47455b5SNico Weber   for (int i = 0; i < 100000; i++)
359b47455b5SNico Weber     Ident(memset)(x, 0, size);
360b47455b5SNico Weber   delete [] x;
361b47455b5SNico Weber }
362b47455b5SNico Weber 
363b47455b5SNico Weber // Same here, but we run memset with small sizes.
TEST(AddressSanitizerInterface,DISABLED_StressSmallMemset)364b47455b5SNico Weber TEST(AddressSanitizerInterface, DISABLED_StressSmallMemset) {
365b47455b5SNico Weber   size_t size = 32;
366b47455b5SNico Weber   char *x = new char[size];
367b47455b5SNico Weber   for (int i = 0; i < 100000000; i++)
368b47455b5SNico Weber     Ident(memset)(x, 0, size);
369b47455b5SNico Weber   delete [] x;
370b47455b5SNico Weber }
371b47455b5SNico Weber static const char *kInvalidPoisonMessage = "invalid-poison-memory-range";
372b47455b5SNico Weber static const char *kInvalidUnpoisonMessage = "invalid-unpoison-memory-range";
373b47455b5SNico Weber 
TEST(AddressSanitizerInterface,DISABLED_InvalidPoisonAndUnpoisonCallsTest)374b47455b5SNico Weber TEST(AddressSanitizerInterface, DISABLED_InvalidPoisonAndUnpoisonCallsTest) {
375b47455b5SNico Weber   char *array = Ident((char*)malloc(120));
376b47455b5SNico Weber   __asan_unpoison_memory_region(array, 120);
377b47455b5SNico Weber   // Try to unpoison not owned memory
378b47455b5SNico Weber   EXPECT_DEATH(__asan_unpoison_memory_region(array, 121),
379b47455b5SNico Weber                kInvalidUnpoisonMessage);
380b47455b5SNico Weber   EXPECT_DEATH(__asan_unpoison_memory_region(array - 1, 120),
381b47455b5SNico Weber                kInvalidUnpoisonMessage);
382b47455b5SNico Weber 
383b47455b5SNico Weber   __asan_poison_memory_region(array, 120);
384b47455b5SNico Weber   // Try to poison not owned memory.
385b47455b5SNico Weber   EXPECT_DEATH(__asan_poison_memory_region(array, 121), kInvalidPoisonMessage);
386b47455b5SNico Weber   EXPECT_DEATH(__asan_poison_memory_region(array - 1, 120),
387b47455b5SNico Weber                kInvalidPoisonMessage);
388b47455b5SNico Weber   free(array);
389b47455b5SNico Weber }
390b47455b5SNico Weber 
TEST(AddressSanitizerInterface,GetOwnershipStressTest)391b47455b5SNico Weber TEST(AddressSanitizerInterface, GetOwnershipStressTest) {
392b47455b5SNico Weber   std::vector<char *> pointers;
393b47455b5SNico Weber   std::vector<size_t> sizes;
394b47455b5SNico Weber   const size_t kNumMallocs = 1 << 9;
395b47455b5SNico Weber   for (size_t i = 0; i < kNumMallocs; i++) {
396b47455b5SNico Weber     size_t size = i * 100 + 1;
397b47455b5SNico Weber     pointers.push_back((char*)malloc(size));
398b47455b5SNico Weber     sizes.push_back(size);
399b47455b5SNico Weber   }
400b47455b5SNico Weber   for (size_t i = 0; i < 4000000; i++) {
401b47455b5SNico Weber     EXPECT_FALSE(__sanitizer_get_ownership(&pointers));
402b47455b5SNico Weber     EXPECT_FALSE(__sanitizer_get_ownership((void*)0x1234));
403b47455b5SNico Weber     size_t idx = i % kNumMallocs;
404b47455b5SNico Weber     EXPECT_TRUE(__sanitizer_get_ownership(pointers[idx]));
405b47455b5SNico Weber     EXPECT_EQ(sizes[idx], __sanitizer_get_allocated_size(pointers[idx]));
406b47455b5SNico Weber   }
407b47455b5SNico Weber   for (size_t i = 0, n = pointers.size(); i < n; i++)
408b47455b5SNico Weber     free(pointers[i]);
409b47455b5SNico Weber }
410b47455b5SNico Weber 
TEST(AddressSanitizerInterface,HandleNoReturnTest)411b47455b5SNico Weber TEST(AddressSanitizerInterface, HandleNoReturnTest) {
412b47455b5SNico Weber   char array[40];
413b47455b5SNico Weber   __asan_poison_memory_region(array, sizeof(array));
414b47455b5SNico Weber   BAD_ACCESS(array, 20);
415b47455b5SNico Weber   __asan_handle_no_return();
416*4b4437c0SVitaly Buka   // Fake stack does not need to be unpoisoned.
417*4b4437c0SVitaly Buka   if (__asan_get_current_fake_stack())
418*4b4437c0SVitaly Buka     return;
419b47455b5SNico Weber   // It unpoisons the whole thread stack.
420b47455b5SNico Weber   GOOD_ACCESS(array, 20);
421b47455b5SNico Weber }
422