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
20const int kAlignment = 8;
21const int kSize = 16;
22
23void test_aligned_alloc() {
24 char *p = (char *) aligned_alloc(alignment: kAlignment, size: kSize);
25 ASSERT_ZERO_LABEL(p);
26 ASSERT_READ_ZERO_LABEL(p, kSize);
27 free(ptr: p);
28}
29
30void test_calloc() {
31 char *p = (char *) calloc(nmemb: kSize, size: 1);
32 ASSERT_ZERO_LABEL(p);
33 ASSERT_READ_ZERO_LABEL(p, kSize);
34 free(ptr: p);
35}
36
37void test_cfree() {
38 // The current glibc does not support cfree.
39}
40
41void test_free() {
42 char *p = (char *) malloc(size: kSize);
43 dfsan_set_label(label: 1, addr: p, size: kSize);
44 free(ptr: p);
45 ASSERT_READ_ZERO_LABEL(p, kSize);
46}
47
48void 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
62void test_malloc() {
63 char *p = (char *) malloc(size: kSize);
64 ASSERT_ZERO_LABEL(p);
65 ASSERT_READ_ZERO_LABEL(p, kSize);
66 free(ptr: p);
67}
68
69void test_malloc_stats() {
70 // Only ensures it does not crash. Our interceptor of malloc_stats is empty.
71 malloc_stats();
72}
73
74void test_malloc_usable_size() {
75 char *p = (char *) malloc(size: kSize);
76 size_t s = malloc_usable_size(ptr: p);
77 assert(s == kSize);
78 ASSERT_ZERO_LABEL(s);
79 free(ptr: p);
80}
81
82void test_mallopt() {
83 int r = mallopt(param: 0, val: 0);
84 assert(!r);
85 ASSERT_ZERO_LABEL(r);
86}
87
88void test_memalign() {
89 char *p = (char *) memalign(alignment: kAlignment, size: kSize);
90 ASSERT_ZERO_LABEL(p);
91 ASSERT_READ_ZERO_LABEL(p, kSize);
92 free(ptr: p);
93}
94
95void test_mmap() {
96 char *p = mmap(NULL, len: kSize, PROT_READ | PROT_WRITE,
97 MAP_PRIVATE | MAP_ANONYMOUS, fd: -1, offset: 0);
98 ASSERT_READ_ZERO_LABEL(p, kSize);
99 char val = 0xff;
100 dfsan_set_label(label: 1, addr: &val, size: sizeof(val));
101 memset(s: p, c: val, n: kSize);
102 p = mmap(addr: p, len: kSize, PROT_READ | PROT_WRITE,
103 MAP_PRIVATE | MAP_ANONYMOUS, fd: -1, offset: 0);
104 ASSERT_READ_ZERO_LABEL(p, kSize);
105 munmap(addr: p, len: kSize);
106}
107
108void test_mmap64() {
109 // The current glibc does not support mmap64.
110}
111
112void test_unmmap() {
113 char *p = mmap(NULL, len: kSize, PROT_READ | PROT_WRITE,
114 MAP_PRIVATE | MAP_ANONYMOUS, fd: -1, offset: 0);
115 char val = 0xff;
116 dfsan_set_label(label: 1, addr: &val, size: sizeof(val));
117 memset(s: p, c: val, n: kSize);
118 munmap(addr: p, len: kSize);
119 ASSERT_READ_ZERO_LABEL(p, kSize);
120}
121
122void test_posix_memalign() {
123 char *p;
124 dfsan_set_label(label: 1, addr: &p, size: sizeof(p));
125 int r = posix_memalign(memptr: (void **)&p, alignment: kAlignment, size: kSize);
126 assert(!r);
127 ASSERT_ZERO_LABEL(p);
128 ASSERT_READ_ZERO_LABEL(p, kSize);
129 free(ptr: p);
130}
131
132void test_pvalloc() {
133 char *p = (char *) pvalloc(size: kSize);
134 ASSERT_ZERO_LABEL(p);
135 ASSERT_READ_ZERO_LABEL(p, kSize);
136 free(ptr: p);
137}
138
139void test_realloc() {
140 char *p = (char *) malloc(size: kSize);
141
142 char *q = (char *) realloc(ptr: p, size: kSize * 2);
143 ASSERT_ZERO_LABEL(q);
144 ASSERT_READ_ZERO_LABEL(q, kSize * 2);
145
146 char *x = (char *) realloc(ptr: q, size: kSize);
147 ASSERT_ZERO_LABEL(x);
148 ASSERT_READ_ZERO_LABEL(x, kSize);
149
150 free(ptr: x);
151}
152
153void test_reallocarray() {
154 // The current glibc does not support reallocarray.
155}
156
157void test_valloc() {
158 char *p = (char *) valloc(size: kSize);
159 ASSERT_ZERO_LABEL(p);
160 ASSERT_READ_ZERO_LABEL(p, kSize);
161 free(ptr: p);
162}
163
164void test___libc_memalign() {
165 // The current glibc does not support __libc_memalign.
166}
167
168void test___tls_get_addr() {
169 // The current glibc does not support __tls_get_addr.
170}
171
172int 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

source code of compiler-rt/test/dfsan/interceptors.c