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