xref: /llvm-project/compiler-rt/test/scudo/interface.cpp (revision f7c5c0d87b8ae5e55006fd3a31994cd68d64f102)
1*f7c5c0d8SMitch Phillips // RUN: %clangxx_scudo %s -lstdc++ -o %t
2*f7c5c0d8SMitch Phillips // RUN:                                                   %run %t ownership          2>&1
3*f7c5c0d8SMitch Phillips // RUN:                                                   %run %t ownership-and-size 2>&1
4*f7c5c0d8SMitch Phillips // RUN:                                                   %run %t heap-size          2>&1
5*f7c5c0d8SMitch Phillips // RUN: %env_scudo_opts="allocator_may_return_null=1"     %run %t soft-limit         2>&1
6*f7c5c0d8SMitch Phillips // RUN: %env_scudo_opts="allocator_may_return_null=1" not %run %t hard-limit         2>&1
7*f7c5c0d8SMitch Phillips 
8*f7c5c0d8SMitch Phillips // Tests that the sanitizer interface functions behave appropriately.
9*f7c5c0d8SMitch Phillips 
10*f7c5c0d8SMitch Phillips #include <assert.h>
11*f7c5c0d8SMitch Phillips #include <stdlib.h>
12*f7c5c0d8SMitch Phillips #include <string.h>
13*f7c5c0d8SMitch Phillips #include <unistd.h>
14*f7c5c0d8SMitch Phillips 
15*f7c5c0d8SMitch Phillips #include <vector>
16*f7c5c0d8SMitch Phillips 
17*f7c5c0d8SMitch Phillips #include <sanitizer/allocator_interface.h>
18*f7c5c0d8SMitch Phillips #include <sanitizer/scudo_interface.h>
19*f7c5c0d8SMitch Phillips 
main(int argc,char ** argv)20*f7c5c0d8SMitch Phillips int main(int argc, char **argv) {
21*f7c5c0d8SMitch Phillips   assert(argc == 2);
22*f7c5c0d8SMitch Phillips 
23*f7c5c0d8SMitch Phillips   if (!strcmp(argv[1], "ownership")) {
24*f7c5c0d8SMitch Phillips     // Ensures that __sanitizer_get_ownership can be called before any other
25*f7c5c0d8SMitch Phillips     // allocator function, and that it behaves properly on a pointer not owned
26*f7c5c0d8SMitch Phillips     // by us.
27*f7c5c0d8SMitch Phillips     assert(!__sanitizer_get_ownership(argv));
28*f7c5c0d8SMitch Phillips   }
29*f7c5c0d8SMitch Phillips   if (!strcmp(argv[1], "ownership-and-size")) {
30*f7c5c0d8SMitch Phillips     // Tests that __sanitizer_get_ownership and __sanitizer_get_allocated_size
31*f7c5c0d8SMitch Phillips     // behave properly on chunks allocated by the Primary and Secondary.
32*f7c5c0d8SMitch Phillips     void *p;
33*f7c5c0d8SMitch Phillips     std::vector<ssize_t> sizes{1, 8, 16, 32, 1024, 32768,
34*f7c5c0d8SMitch Phillips                                1 << 16, 1 << 17, 1 << 20, 1 << 24};
35*f7c5c0d8SMitch Phillips     for (size_t size : sizes) {
36*f7c5c0d8SMitch Phillips       p = malloc(size);
37*f7c5c0d8SMitch Phillips       assert(p);
38*f7c5c0d8SMitch Phillips       assert(__sanitizer_get_ownership(p));
39*f7c5c0d8SMitch Phillips       assert(__sanitizer_get_allocated_size(p) >= size);
40*f7c5c0d8SMitch Phillips       free(p);
41*f7c5c0d8SMitch Phillips     }
42*f7c5c0d8SMitch Phillips   }
43*f7c5c0d8SMitch Phillips   if (!strcmp(argv[1], "heap-size")) {
44*f7c5c0d8SMitch Phillips     // Ensures that __sanitizer_get_heap_size can be called before any other
45*f7c5c0d8SMitch Phillips     // allocator function.
46*f7c5c0d8SMitch Phillips     assert(__sanitizer_get_heap_size() >= 0);
47*f7c5c0d8SMitch Phillips   }
48*f7c5c0d8SMitch Phillips   if (!strcmp(argv[1], "soft-limit")) {
49*f7c5c0d8SMitch Phillips     // Verifies that setting the soft RSS limit at runtime works as expected.
50*f7c5c0d8SMitch Phillips     std::vector<void *> pointers;
51*f7c5c0d8SMitch Phillips     size_t size = 1 << 19; // 512Kb
52*f7c5c0d8SMitch Phillips     for (int i = 0; i < 5; i++) {
53*f7c5c0d8SMitch Phillips       void *p = malloc(size);
54*f7c5c0d8SMitch Phillips       memset(p, 0, size);
55*f7c5c0d8SMitch Phillips       pointers.push_back(p);
56*f7c5c0d8SMitch Phillips     }
57*f7c5c0d8SMitch Phillips     // Set the soft RSS limit to 1Mb.
58*f7c5c0d8SMitch Phillips     __scudo_set_rss_limit(1, 0);
59*f7c5c0d8SMitch Phillips     usleep(20000);
60*f7c5c0d8SMitch Phillips     // The following allocation should return NULL.
61*f7c5c0d8SMitch Phillips     void *p = malloc(size);
62*f7c5c0d8SMitch Phillips     assert(!p);
63*f7c5c0d8SMitch Phillips     // Remove the soft RSS limit.
64*f7c5c0d8SMitch Phillips     __scudo_set_rss_limit(0, 0);
65*f7c5c0d8SMitch Phillips     // The following allocation should succeed.
66*f7c5c0d8SMitch Phillips     p = malloc(size);
67*f7c5c0d8SMitch Phillips     assert(p);
68*f7c5c0d8SMitch Phillips     free(p);
69*f7c5c0d8SMitch Phillips     while (!pointers.empty()) {
70*f7c5c0d8SMitch Phillips       free(pointers.back());
71*f7c5c0d8SMitch Phillips       pointers.pop_back();
72*f7c5c0d8SMitch Phillips     }
73*f7c5c0d8SMitch Phillips   }
74*f7c5c0d8SMitch Phillips   if (!strcmp(argv[1], "hard-limit")) {
75*f7c5c0d8SMitch Phillips     // Verifies that setting the hard RSS limit at runtime works as expected.
76*f7c5c0d8SMitch Phillips     std::vector<void *> pointers;
77*f7c5c0d8SMitch Phillips     size_t size = 1 << 19; // 512Kb
78*f7c5c0d8SMitch Phillips     for (int i = 0; i < 5; i++) {
79*f7c5c0d8SMitch Phillips       void *p = malloc(size);
80*f7c5c0d8SMitch Phillips       memset(p, 0, size);
81*f7c5c0d8SMitch Phillips       pointers.push_back(p);
82*f7c5c0d8SMitch Phillips     }
83*f7c5c0d8SMitch Phillips     // Set the hard RSS limit to 1Mb
84*f7c5c0d8SMitch Phillips     __scudo_set_rss_limit(1, 1);
85*f7c5c0d8SMitch Phillips     usleep(20000);
86*f7c5c0d8SMitch Phillips     // The following should trigger our death.
87*f7c5c0d8SMitch Phillips     void *p = malloc(size);
88*f7c5c0d8SMitch Phillips   }
89*f7c5c0d8SMitch Phillips 
90*f7c5c0d8SMitch Phillips   return 0;
91*f7c5c0d8SMitch Phillips }
92