asan_noinst_test.cc revision e5f5895bda30f374b0b51412fd4d837fa59aed66
1//===-- asan_noinst_test.cc ----------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11//
12// This test file should be compiled w/o asan instrumentation.
13//===----------------------------------------------------------------------===//
14#include "asan_allocator.h"
15#include "asan_interface.h"
16#include "asan_internal.h"
17#include "asan_mapping.h"
18#include "asan_stack.h"
19#include "asan_test_utils.h"
20
21#include <assert.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <vector>
25#include <algorithm>
26#include "gtest/gtest.h"
27
28// Simple stand-alone pseudorandom number generator.
29// Current algorithm is ANSI C linear congruential PRNG.
30static inline u32 my_rand(u32* state) {
31  return (*state = *state * 1103515245 + 12345) >> 16;
32}
33
34static u32 global_seed = 0;
35
36
37TEST(AddressSanitizer, InternalSimpleDeathTest) {
38  EXPECT_DEATH(exit(1), "");
39}
40
41static void MallocStress(size_t n) {
42  u32 seed = my_rand(&global_seed);
43  __asan::AsanStackTrace stack1;
44  stack1.trace[0] = 0xa123;
45  stack1.trace[1] = 0xa456;
46  stack1.size = 2;
47
48  __asan::AsanStackTrace stack2;
49  stack2.trace[0] = 0xb123;
50  stack2.trace[1] = 0xb456;
51  stack2.size = 2;
52
53  __asan::AsanStackTrace stack3;
54  stack3.trace[0] = 0xc123;
55  stack3.trace[1] = 0xc456;
56  stack3.size = 2;
57
58  std::vector<void *> vec;
59  for (size_t i = 0; i < n; i++) {
60    if ((i % 3) == 0) {
61      if (vec.empty()) continue;
62      size_t idx = my_rand(&seed) % vec.size();
63      void *ptr = vec[idx];
64      vec[idx] = vec.back();
65      vec.pop_back();
66      __asan::asan_free(ptr, &stack1);
67    } else {
68      size_t size = my_rand(&seed) % 1000 + 1;
69      switch ((my_rand(&seed) % 128)) {
70        case 0: size += 1024; break;
71        case 1: size += 2048; break;
72        case 2: size += 4096; break;
73      }
74      size_t alignment = 1 << (my_rand(&seed) % 10 + 1);
75      char *ptr = (char*)__asan::asan_memalign(alignment, size, &stack2);
76      vec.push_back(ptr);
77      ptr[0] = 0;
78      ptr[size-1] = 0;
79      ptr[size/2] = 0;
80    }
81  }
82  for (size_t i = 0; i < vec.size(); i++)
83    __asan::asan_free(vec[i], &stack3);
84}
85
86
87TEST(AddressSanitizer, NoInstMallocTest) {
88#ifdef __arm__
89  MallocStress(300000);
90#else
91  MallocStress(1000000);
92#endif
93}
94
95static void PrintShadow(const char *tag, uptr ptr, size_t size) {
96  fprintf(stderr, "%s shadow: %lx size % 3ld: ", tag, (long)ptr, (long)size);
97  uptr prev_shadow = 0;
98  for (sptr i = -32; i < (sptr)size + 32; i++) {
99    uptr shadow = __asan::MemToShadow(ptr + i);
100    if (i == 0 || i == (sptr)size)
101      fprintf(stderr, ".");
102    if (shadow != prev_shadow) {
103      prev_shadow = shadow;
104      fprintf(stderr, "%02x", (int)*(u8*)shadow);
105    }
106  }
107  fprintf(stderr, "\n");
108}
109
110TEST(AddressSanitizer, DISABLED_InternalPrintShadow) {
111  for (size_t size = 1; size <= 513; size++) {
112    char *ptr = new char[size];
113    PrintShadow("m", (uptr)ptr, size);
114    delete [] ptr;
115    PrintShadow("f", (uptr)ptr, size);
116  }
117}
118
119static uptr pc_array[] = {
120#if __WORDSIZE == 64
121  0x7effbf756068ULL,
122  0x7effbf75e5abULL,
123  0x7effc0625b7cULL,
124  0x7effc05b8997ULL,
125  0x7effbf990577ULL,
126  0x7effbf990c56ULL,
127  0x7effbf992f3cULL,
128  0x7effbf950c22ULL,
129  0x7effc036dba0ULL,
130  0x7effc03638a3ULL,
131  0x7effc035be4aULL,
132  0x7effc0539c45ULL,
133  0x7effc0539a65ULL,
134  0x7effc03db9b3ULL,
135  0x7effc03db100ULL,
136  0x7effc037c7b8ULL,
137  0x7effc037bfffULL,
138  0x7effc038b777ULL,
139  0x7effc038021cULL,
140  0x7effc037c7d1ULL,
141  0x7effc037bfffULL,
142  0x7effc038b777ULL,
143  0x7effc038021cULL,
144  0x7effc037c7d1ULL,
145  0x7effc037bfffULL,
146  0x7effc038b777ULL,
147  0x7effc038021cULL,
148  0x7effc037c7d1ULL,
149  0x7effc037bfffULL,
150  0x7effc0520d26ULL,
151  0x7effc009ddffULL,
152  0x7effbf90bb50ULL,
153  0x7effbdddfa69ULL,
154  0x7effbdde1fe2ULL,
155  0x7effbdde2424ULL,
156  0x7effbdde27b3ULL,
157  0x7effbddee53bULL,
158  0x7effbdde1988ULL,
159  0x7effbdde0904ULL,
160  0x7effc106ce0dULL,
161  0x7effbcc3fa04ULL,
162  0x7effbcc3f6a4ULL,
163  0x7effbcc3e726ULL,
164  0x7effbcc40852ULL,
165  0x7effb681ec4dULL,
166#endif  // __WORDSIZE
167  0xB0B5E768,
168  0x7B682EC1,
169  0x367F9918,
170  0xAE34E13,
171  0xBA0C6C6,
172  0x13250F46,
173  0xA0D6A8AB,
174  0x2B07C1A8,
175  0x6C844F4A,
176  0x2321B53,
177  0x1F3D4F8F,
178  0x3FE2924B,
179  0xB7A2F568,
180  0xBD23950A,
181  0x61020930,
182  0x33E7970C,
183  0x405998A1,
184  0x59F3551D,
185  0x350E3028,
186  0xBC55A28D,
187  0x361F3AED,
188  0xBEAD0F73,
189  0xAEF28479,
190  0x757E971F,
191  0xAEBA450,
192  0x43AD22F5,
193  0x8C2C50C4,
194  0x7AD8A2E1,
195  0x69EE4EE8,
196  0xC08DFF,
197  0x4BA6538,
198  0x3708AB2,
199  0xC24B6475,
200  0x7C8890D7,
201  0x6662495F,
202  0x9B641689,
203  0xD3596B,
204  0xA1049569,
205  0x44CBC16,
206  0x4D39C39F
207};
208
209void CompressStackTraceTest(size_t n_iter) {
210  u32 seed = my_rand(&global_seed);
211  const size_t kNumPcs = ASAN_ARRAY_SIZE(pc_array);
212  u32 compressed[2 * kNumPcs];
213
214  for (size_t iter = 0; iter < n_iter; iter++) {
215    std::random_shuffle(pc_array, pc_array + kNumPcs);
216    __asan::AsanStackTrace stack0, stack1;
217    stack0.CopyFrom(pc_array, kNumPcs);
218    stack0.size = std::max((size_t)1, (size_t)(my_rand(&seed) % stack0.size));
219    size_t compress_size =
220      std::max((size_t)2, (size_t)my_rand(&seed) % (2 * kNumPcs));
221    size_t n_frames =
222      __asan::AsanStackTrace::CompressStack(&stack0, compressed, compress_size);
223    assert(n_frames <= stack0.size);
224    __asan::AsanStackTrace::UncompressStack(&stack1, compressed, compress_size);
225    assert(stack1.size == n_frames);
226    for (size_t i = 0; i < stack1.size; i++) {
227      assert(stack0.trace[i] == stack1.trace[i]);
228    }
229  }
230}
231
232TEST(AddressSanitizer, CompressStackTraceTest) {
233  CompressStackTraceTest(10000);
234}
235
236void CompressStackTraceBenchmark(size_t n_iter) {
237  const size_t kNumPcs = ASAN_ARRAY_SIZE(pc_array);
238  u32 compressed[2 * kNumPcs];
239  std::random_shuffle(pc_array, pc_array + kNumPcs);
240
241  __asan::AsanStackTrace stack0;
242  stack0.CopyFrom(pc_array, kNumPcs);
243  stack0.size = kNumPcs;
244  for (size_t iter = 0; iter < n_iter; iter++) {
245    size_t compress_size = kNumPcs;
246    size_t n_frames =
247      __asan::AsanStackTrace::CompressStack(&stack0, compressed, compress_size);
248    Ident(n_frames);
249  }
250}
251
252TEST(AddressSanitizer, CompressStackTraceBenchmark) {
253  CompressStackTraceBenchmark(1 << 24);
254}
255
256TEST(AddressSanitizer, QuarantineTest) {
257  __asan::AsanStackTrace stack;
258  stack.trace[0] = 0x890;
259  stack.size = 1;
260
261  const int size = 32;
262  void *p = __asan::asan_malloc(size, &stack);
263  __asan::asan_free(p, &stack);
264  size_t i;
265  size_t max_i = 1 << 30;
266  for (i = 0; i < max_i; i++) {
267    void *p1 = __asan::asan_malloc(size, &stack);
268    __asan::asan_free(p1, &stack);
269    if (p1 == p) break;
270  }
271  // fprintf(stderr, "i=%ld\n", i);
272  EXPECT_GE(i, 100000U);
273  EXPECT_LT(i, max_i);
274}
275
276void *ThreadedQuarantineTestWorker(void *unused) {
277  u32 seed = my_rand(&global_seed);
278  __asan::AsanStackTrace stack;
279  stack.trace[0] = 0x890;
280  stack.size = 1;
281
282  for (size_t i = 0; i < 1000; i++) {
283    void *p = __asan::asan_malloc(1 + (my_rand(&seed) % 4000), &stack);
284    __asan::asan_free(p, &stack);
285  }
286  return NULL;
287}
288
289// Check that the thread local allocators are flushed when threads are
290// destroyed.
291TEST(AddressSanitizer, ThreadedQuarantineTest) {
292  const int n_threads = 3000;
293  size_t mmaped1 = __asan_get_heap_size();
294  for (int i = 0; i < n_threads; i++) {
295    pthread_t t;
296    pthread_create(&t, NULL, ThreadedQuarantineTestWorker, 0);
297    pthread_join(t, 0);
298    size_t mmaped2 = __asan_get_heap_size();
299    EXPECT_LT(mmaped2 - mmaped1, 320U * (1 << 20));
300  }
301}
302
303void *ThreadedOneSizeMallocStress(void *unused) {
304  __asan::AsanStackTrace stack;
305  stack.trace[0] = 0x890;
306  stack.size = 1;
307  const size_t kNumMallocs = 1000;
308  for (int iter = 0; iter < 1000; iter++) {
309    void *p[kNumMallocs];
310    for (size_t i = 0; i < kNumMallocs; i++) {
311      p[i] = __asan::asan_malloc(32, &stack);
312    }
313    for (size_t i = 0; i < kNumMallocs; i++) {
314      __asan::asan_free(p[i], &stack);
315    }
316  }
317  return NULL;
318}
319
320TEST(AddressSanitizer, ThreadedOneSizeMallocStressTest) {
321  const int kNumThreads = 4;
322  pthread_t t[kNumThreads];
323  for (int i = 0; i < kNumThreads; i++) {
324    pthread_create(&t[i], 0, ThreadedOneSizeMallocStress, 0);
325  }
326  for (int i = 0; i < kNumThreads; i++) {
327    pthread_join(t[i], 0);
328  }
329}
330