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