1*f7c5c0d8SMitch Phillips // RUN: %clang_scudo %s -o %t
2*f7c5c0d8SMitch Phillips // RUN: %env_scudo_opts="QuarantineSizeMb=1:QuarantineSizeKb=64" not %run %t unused 2>&1
3*f7c5c0d8SMitch Phillips // RUN: %env_scudo_opts="QuarantineSizeMb=1:QuarantineChunksUpToSize=256" not %run %t unused 2>&1
4*f7c5c0d8SMitch Phillips // RUN: %env_scudo_opts="QuarantineSizeKb=0:ThreadLocalQuarantineSizeKb=0" %run %t zeroquarantine 2>&1
5*f7c5c0d8SMitch Phillips // RUN: %env_scudo_opts=QuarantineSizeKb=64 %run %t smallquarantine 2>&1
6*f7c5c0d8SMitch Phillips // RUN: %env_scudo_opts=QuarantineChunksUpToSize=256 %run %t threshold 2>&1
7*f7c5c0d8SMitch Phillips // RUN: %env_scudo_opts="QuarantineSizeMb=1" %run %t oldquarantine 2>&1
8*f7c5c0d8SMitch Phillips
9*f7c5c0d8SMitch Phillips // Tests that the quarantine prevents a chunk from being reused right away.
10*f7c5c0d8SMitch Phillips // Also tests that a chunk will eventually become available again for
11*f7c5c0d8SMitch Phillips // allocation when the recycling criteria has been met. Finally, tests the
12*f7c5c0d8SMitch Phillips // threshold up to which a chunk is quarantine, and the old quarantine behavior.
13*f7c5c0d8SMitch Phillips
14*f7c5c0d8SMitch Phillips #include <assert.h>
15*f7c5c0d8SMitch Phillips #include <malloc.h>
16*f7c5c0d8SMitch Phillips #include <stdlib.h>
17*f7c5c0d8SMitch Phillips #include <string.h>
18*f7c5c0d8SMitch Phillips
19*f7c5c0d8SMitch Phillips #include <sanitizer/allocator_interface.h>
20*f7c5c0d8SMitch Phillips
main(int argc,char ** argv)21*f7c5c0d8SMitch Phillips int main(int argc, char **argv) {
22*f7c5c0d8SMitch Phillips void *p, *old_p;
23*f7c5c0d8SMitch Phillips size_t allocated_bytes, size = 1U << 8, alignment = 1U << 8;
24*f7c5c0d8SMitch Phillips
25*f7c5c0d8SMitch Phillips assert(argc == 2);
26*f7c5c0d8SMitch Phillips // First, warm up the allocator for the classes used.
27*f7c5c0d8SMitch Phillips p = malloc(size);
28*f7c5c0d8SMitch Phillips assert(p);
29*f7c5c0d8SMitch Phillips free(p);
30*f7c5c0d8SMitch Phillips p = malloc(size + 1);
31*f7c5c0d8SMitch Phillips assert(p);
32*f7c5c0d8SMitch Phillips free(p);
33*f7c5c0d8SMitch Phillips assert(posix_memalign(&p, alignment, size) == 0);
34*f7c5c0d8SMitch Phillips assert(p);
35*f7c5c0d8SMitch Phillips free(p);
36*f7c5c0d8SMitch Phillips assert(posix_memalign(&p, alignment, size + 1) == 0);
37*f7c5c0d8SMitch Phillips assert(p);
38*f7c5c0d8SMitch Phillips free(p);
39*f7c5c0d8SMitch Phillips
40*f7c5c0d8SMitch Phillips if (!strcmp(argv[1], "zeroquarantine")) {
41*f7c5c0d8SMitch Phillips // Verifies that a chunk is deallocated right away when the local and
42*f7c5c0d8SMitch Phillips // global quarantine sizes are 0.
43*f7c5c0d8SMitch Phillips allocated_bytes = __sanitizer_get_current_allocated_bytes();
44*f7c5c0d8SMitch Phillips p = malloc(size);
45*f7c5c0d8SMitch Phillips assert(p);
46*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
47*f7c5c0d8SMitch Phillips free(p);
48*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() == allocated_bytes);
49*f7c5c0d8SMitch Phillips }
50*f7c5c0d8SMitch Phillips if (!strcmp(argv[1], "smallquarantine")) {
51*f7c5c0d8SMitch Phillips // The delayed freelist will prevent a chunk from being available right
52*f7c5c0d8SMitch Phillips // away.
53*f7c5c0d8SMitch Phillips p = malloc(size);
54*f7c5c0d8SMitch Phillips assert(p);
55*f7c5c0d8SMitch Phillips old_p = p;
56*f7c5c0d8SMitch Phillips free(p);
57*f7c5c0d8SMitch Phillips p = malloc(size);
58*f7c5c0d8SMitch Phillips assert(p);
59*f7c5c0d8SMitch Phillips assert(old_p != p);
60*f7c5c0d8SMitch Phillips free(p);
61*f7c5c0d8SMitch Phillips
62*f7c5c0d8SMitch Phillips // Eventually the chunk should become available again.
63*f7c5c0d8SMitch Phillips char found = 0;
64*f7c5c0d8SMitch Phillips for (int i = 0; i < 0x200 && !found; i++) {
65*f7c5c0d8SMitch Phillips p = malloc(size);
66*f7c5c0d8SMitch Phillips assert(p);
67*f7c5c0d8SMitch Phillips found = (p == old_p);
68*f7c5c0d8SMitch Phillips free(p);
69*f7c5c0d8SMitch Phillips }
70*f7c5c0d8SMitch Phillips assert(found);
71*f7c5c0d8SMitch Phillips }
72*f7c5c0d8SMitch Phillips if (!strcmp(argv[1], "threshold")) {
73*f7c5c0d8SMitch Phillips // Verifies that a chunk of size greater than the threshold will be freed
74*f7c5c0d8SMitch Phillips // right away. Alignment has no impact on the threshold.
75*f7c5c0d8SMitch Phillips allocated_bytes = __sanitizer_get_current_allocated_bytes();
76*f7c5c0d8SMitch Phillips p = malloc(size + 1);
77*f7c5c0d8SMitch Phillips assert(p);
78*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
79*f7c5c0d8SMitch Phillips free(p);
80*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() == allocated_bytes);
81*f7c5c0d8SMitch Phillips assert(posix_memalign(&p, alignment, size + 1) == 0);
82*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
83*f7c5c0d8SMitch Phillips free(p);
84*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() == allocated_bytes);
85*f7c5c0d8SMitch Phillips // Verifies that a chunk of size lower or equal to the threshold will be
86*f7c5c0d8SMitch Phillips // quarantined.
87*f7c5c0d8SMitch Phillips p = malloc(size);
88*f7c5c0d8SMitch Phillips assert(p);
89*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
90*f7c5c0d8SMitch Phillips free(p);
91*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
92*f7c5c0d8SMitch Phillips allocated_bytes = __sanitizer_get_current_allocated_bytes();
93*f7c5c0d8SMitch Phillips assert(posix_memalign(&p, alignment, size) == 0);
94*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
95*f7c5c0d8SMitch Phillips free(p);
96*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
97*f7c5c0d8SMitch Phillips }
98*f7c5c0d8SMitch Phillips if (!strcmp(argv[1], "oldquarantine")) {
99*f7c5c0d8SMitch Phillips // Verifies that we quarantine everything if the deprecated quarantine
100*f7c5c0d8SMitch Phillips // option is specified. Alignment has no impact on the threshold.
101*f7c5c0d8SMitch Phillips allocated_bytes = __sanitizer_get_current_allocated_bytes();
102*f7c5c0d8SMitch Phillips p = malloc(size);
103*f7c5c0d8SMitch Phillips assert(p);
104*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
105*f7c5c0d8SMitch Phillips free(p);
106*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
107*f7c5c0d8SMitch Phillips allocated_bytes = __sanitizer_get_current_allocated_bytes();
108*f7c5c0d8SMitch Phillips assert(posix_memalign(&p, alignment, size) == 0);
109*f7c5c0d8SMitch Phillips assert(p);
110*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
111*f7c5c0d8SMitch Phillips free(p);
112*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
113*f7c5c0d8SMitch Phillips // Secondary backed allocation.
114*f7c5c0d8SMitch Phillips allocated_bytes = __sanitizer_get_current_allocated_bytes();
115*f7c5c0d8SMitch Phillips p = malloc(1U << 19);
116*f7c5c0d8SMitch Phillips assert(p);
117*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
118*f7c5c0d8SMitch Phillips free(p);
119*f7c5c0d8SMitch Phillips assert(__sanitizer_get_current_allocated_bytes() > allocated_bytes);
120*f7c5c0d8SMitch Phillips }
121*f7c5c0d8SMitch Phillips
122*f7c5c0d8SMitch Phillips return 0;
123*f7c5c0d8SMitch Phillips }
124