xref: /llvm-project/compiler-rt/test/dfsan/interceptors.c (revision 3ffda42e50703b5402966eba3f30cd1dcad4b022)
1 // RUN: %clang_dfsan -mllvm -dfsan-combine-pointer-labels-on-load=false %s -o %t && %run %t
2 // RUN: %clang_dfsan -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -mllvm -dfsan-combine-pointer-labels-on-load=false %s -o %t && %run %t
3 //
4 // Tests custom implementations of various glibc functions.
5 
6 #include <sanitizer/dfsan_interface.h>
7 
8 #include <assert.h>
9 #include <malloc.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/mman.h>
13 
14 #define ASSERT_ZERO_LABEL(data) \
15   assert(0 == dfsan_get_label((long) (data)))
16 
17 #define ASSERT_READ_ZERO_LABEL(ptr, size) \
18   assert(0 == dfsan_read_label(ptr, size))
19 
20 const int kAlignment = 8;
21 const int kSize = 16;
22 
test_aligned_alloc()23 void test_aligned_alloc() {
24   char *p = (char *) aligned_alloc(kAlignment, kSize);
25   ASSERT_ZERO_LABEL(p);
26   ASSERT_READ_ZERO_LABEL(p, kSize);
27   free(p);
28 }
29 
test_calloc()30 void test_calloc() {
31   char *p = (char *) calloc(kSize, 1);
32   ASSERT_ZERO_LABEL(p);
33   ASSERT_READ_ZERO_LABEL(p, kSize);
34   free(p);
35 }
36 
test_cfree()37 void test_cfree() {
38   // The current glibc does not support cfree.
39 }
40 
test_free()41 void test_free() {
42   char *p = (char *) malloc(kSize);
43   dfsan_set_label(1, p, kSize);
44   free(p);
45   ASSERT_READ_ZERO_LABEL(p, kSize);
46 }
47 
test_mallinfo()48 void test_mallinfo() {
49   // The mallinfo interceptor takes an argument instead of returning a struct.
50   // This doesn't work on AArch64 which uses different registers for the two
51   // function types.
52 #if defined(__GLIBC__) && !defined(__aarch64__)
53   struct mallinfo mi = mallinfo();
54   for (int i = 0; i < sizeof(struct mallinfo); ++i) {
55     char c = ((char *)(&mi))[i];
56     assert(!c);
57     ASSERT_ZERO_LABEL(c);
58   }
59 #endif
60 }
61 
test_malloc()62 void test_malloc() {
63   char *p = (char *) malloc(kSize);
64   ASSERT_ZERO_LABEL(p);
65   ASSERT_READ_ZERO_LABEL(p, kSize);
66   free(p);
67 }
68 
test_malloc_stats()69 void test_malloc_stats() {
70   // Only ensures it does not crash. Our interceptor of malloc_stats is empty.
71   malloc_stats();
72 }
73 
test_malloc_usable_size()74 void test_malloc_usable_size() {
75   char *p = (char *) malloc(kSize);
76   size_t s = malloc_usable_size(p);
77   assert(s == kSize);
78   ASSERT_ZERO_LABEL(s);
79   free(p);
80 }
81 
test_mallopt()82 void test_mallopt() {
83   int r = mallopt(0, 0);
84   assert(!r);
85   ASSERT_ZERO_LABEL(r);
86 }
87 
test_memalign()88 void test_memalign() {
89   char *p = (char *) memalign(kAlignment, kSize);
90   ASSERT_ZERO_LABEL(p);
91   ASSERT_READ_ZERO_LABEL(p, kSize);
92   free(p);
93 }
94 
test_mmap()95 void test_mmap() {
96   char *p = mmap(NULL, kSize, PROT_READ | PROT_WRITE,
97                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
98   ASSERT_READ_ZERO_LABEL(p, kSize);
99   char val = 0xff;
100   dfsan_set_label(1, &val, sizeof(val));
101   memset(p, val, kSize);
102   p = mmap(p, kSize, PROT_READ | PROT_WRITE,
103            MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
104   ASSERT_READ_ZERO_LABEL(p, kSize);
105   munmap(p, kSize);
106 }
107 
test_mmap64()108 void test_mmap64() {
109   // The current glibc does not support mmap64.
110 }
111 
test_unmmap()112 void test_unmmap() {
113   char *p = mmap(NULL, kSize, PROT_READ | PROT_WRITE,
114                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
115   char val = 0xff;
116   dfsan_set_label(1, &val, sizeof(val));
117   memset(p, val, kSize);
118   munmap(p, kSize);
119   ASSERT_READ_ZERO_LABEL(p, kSize);
120 }
121 
test_posix_memalign()122 void test_posix_memalign() {
123   char *p;
124   dfsan_set_label(1, &p, sizeof(p));
125   int r = posix_memalign((void **)&p, kAlignment, kSize);
126   assert(!r);
127   ASSERT_ZERO_LABEL(p);
128   ASSERT_READ_ZERO_LABEL(p, kSize);
129   free(p);
130 }
131 
test_pvalloc()132 void test_pvalloc() {
133   char *p = (char *) pvalloc(kSize);
134   ASSERT_ZERO_LABEL(p);
135   ASSERT_READ_ZERO_LABEL(p, kSize);
136   free(p);
137 }
138 
test_realloc()139 void test_realloc() {
140   char *p = (char *) malloc(kSize);
141 
142   char *q = (char *) realloc(p, kSize * 2);
143   ASSERT_ZERO_LABEL(q);
144   ASSERT_READ_ZERO_LABEL(q, kSize * 2);
145 
146   char *x = (char *) realloc(q, kSize);
147   ASSERT_ZERO_LABEL(x);
148   ASSERT_READ_ZERO_LABEL(x, kSize);
149 
150   free(x);
151 }
152 
test_reallocarray()153 void test_reallocarray() {
154   // The current glibc does not support reallocarray.
155 }
156 
test_valloc()157 void test_valloc() {
158   char *p = (char *) valloc(kSize);
159   ASSERT_ZERO_LABEL(p);
160   ASSERT_READ_ZERO_LABEL(p, kSize);
161   free(p);
162 }
163 
test___libc_memalign()164 void test___libc_memalign() {
165   // The current glibc does not support __libc_memalign.
166 }
167 
test___tls_get_addr()168 void test___tls_get_addr() {
169   // The current glibc does not support __tls_get_addr.
170 }
171 
main(void)172 int main(void) {
173   // With any luck this sequence of calls will cause allocators to return the
174   // same pointer. This is probably the best we can do to test these functions.
175   test_aligned_alloc();
176   test_calloc();
177   test_cfree();
178   test_free();
179   test_mallinfo();
180   test_malloc();
181   test_malloc_stats();
182   test_malloc_usable_size();
183   test_mallopt();
184   test_memalign();
185   test_mmap();
186   test_mmap64();
187   test_unmmap();
188   test_posix_memalign();
189   test_pvalloc();
190   test_realloc();
191   test_reallocarray();
192   test_valloc();
193   test___libc_memalign();
194   test___tls_get_addr();
195 }
196