]> git.proxmox.com Git - rustc.git/blame - src/compiler-rt/test/dfsan/custom.cc
New upstream version 1.19.0+dfsg1
[rustc.git] / src / compiler-rt / test / dfsan / custom.cc
CommitLineData
92a42be0
SL
1// RUN: %clang_dfsan %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
2// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
3// RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES %s -o %t && %run %t
4// RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES -mllvm -dfsan-args-abi %s -o %t && %run %t
1a4d82fc 5
7cac9316
XL
6// XFAIL: target-is-mips64el
7
1a4d82fc
JJ
8// Tests custom implementations of various glibc functions.
9
1a4d82fc
JJ
10#include <sanitizer/dfsan_interface.h>
11
12#include <arpa/inet.h>
13#include <assert.h>
14#include <fcntl.h>
15#include <link.h>
16#include <poll.h>
17#include <pthread.h>
18#include <pwd.h>
19#include <sched.h>
20#include <signal.h>
21#include <stdio.h>
92a42be0 22#include <stdint.h>
1a4d82fc
JJ
23#include <stdlib.h>
24#include <string.h>
25#include <sys/select.h>
26#include <sys/resource.h>
27#include <sys/stat.h>
28#include <sys/time.h>
29#include <sys/types.h>
30#include <time.h>
31#include <unistd.h>
32
33dfsan_label i_label = 0;
34dfsan_label j_label = 0;
35dfsan_label k_label = 0;
36dfsan_label i_j_label = 0;
37
38#define ASSERT_ZERO_LABEL(data) \
39 assert(0 == dfsan_get_label((long) (data)))
40
41#define ASSERT_READ_ZERO_LABEL(ptr, size) \
42 assert(0 == dfsan_read_label(ptr, size))
43
44#define ASSERT_LABEL(data, label) \
45 assert(label == dfsan_get_label((long) (data)))
46
47#define ASSERT_READ_LABEL(ptr, size, label) \
48 assert(label == dfsan_read_label(ptr, size))
49
50void test_stat() {
51 int i = 1;
52 dfsan_set_label(i_label, &i, sizeof(i));
53
54 struct stat s;
55 s.st_dev = i;
56 assert(0 == stat("/", &s));
57 ASSERT_ZERO_LABEL(s.st_dev);
58
59 s.st_dev = i;
60 assert(-1 == stat("/nonexistent", &s));
61 ASSERT_LABEL(s.st_dev, i_label);
62}
63
64void test_fstat() {
65 int i = 1;
66 dfsan_set_label(i_label, &i, sizeof(i));
67
68 struct stat s;
69 int fd = open("/dev/zero", O_RDONLY);
70 s.st_dev = i;
71 int rv = fstat(fd, &s);
72 assert(0 == rv);
73 ASSERT_ZERO_LABEL(s.st_dev);
74}
75
76void test_memcmp() {
77 char str1[] = "str1", str2[] = "str2";
78 dfsan_set_label(i_label, &str1[3], 1);
79 dfsan_set_label(j_label, &str2[3], 1);
80
81 int rv = memcmp(str1, str2, sizeof(str1));
82 assert(rv < 0);
83#ifdef STRICT_DATA_DEPENDENCIES
84 ASSERT_ZERO_LABEL(rv);
85#else
86 ASSERT_LABEL(rv, i_j_label);
87#endif
88}
89
90void test_memcpy() {
91 char str1[] = "str1";
92 char str2[sizeof(str1)];
93 dfsan_set_label(i_label, &str1[3], 1);
94
95 ASSERT_ZERO_LABEL(memcpy(str2, str1, sizeof(str1)));
96 assert(0 == memcmp(str2, str1, sizeof(str1)));
97 ASSERT_ZERO_LABEL(str2[0]);
98 ASSERT_LABEL(str2[3], i_label);
99}
100
101void test_memset() {
102 char buf[8];
103 int j = 'a';
104 dfsan_set_label(j_label, &j, sizeof(j));
105
106 ASSERT_ZERO_LABEL(memset(&buf, j, sizeof(buf)));
107 for (int i = 0; i < 8; ++i) {
108 ASSERT_LABEL(buf[i], j_label);
109 assert(buf[i] == 'a');
110 }
111}
112
113void test_strcmp() {
114 char str1[] = "str1", str2[] = "str2";
115 dfsan_set_label(i_label, &str1[3], 1);
116 dfsan_set_label(j_label, &str2[3], 1);
117
118 int rv = strcmp(str1, str2);
119 assert(rv < 0);
120#ifdef STRICT_DATA_DEPENDENCIES
121 ASSERT_ZERO_LABEL(rv);
122#else
123 ASSERT_LABEL(rv, i_j_label);
124#endif
125}
126
127void test_strlen() {
128 char str1[] = "str1";
129 dfsan_set_label(i_label, &str1[3], 1);
130
131 int rv = strlen(str1);
132 assert(rv == 4);
133#ifdef STRICT_DATA_DEPENDENCIES
134 ASSERT_ZERO_LABEL(rv);
135#else
136 ASSERT_LABEL(rv, i_label);
137#endif
138}
139
140void test_strdup() {
141 char str1[] = "str1";
142 dfsan_set_label(i_label, &str1[3], 1);
143
144 char *strd = strdup(str1);
145 ASSERT_ZERO_LABEL(strd[0]);
146 ASSERT_LABEL(strd[3], i_label);
147 free(strd);
148}
149
150void test_strncpy() {
151 char str1[] = "str1";
152 char str2[sizeof(str1)];
153 dfsan_set_label(i_label, &str1[3], 1);
154
155 char *strd = strncpy(str2, str1, 5);
156 assert(strd == str2);
157 assert(strcmp(str1, str2) == 0);
158 ASSERT_ZERO_LABEL(strd);
159 ASSERT_ZERO_LABEL(strd[0]);
160 ASSERT_ZERO_LABEL(strd[1]);
161 ASSERT_ZERO_LABEL(strd[2]);
162 ASSERT_LABEL(strd[3], i_label);
163
164 strd = strncpy(str2, str1, 3);
165 assert(strd == str2);
166 assert(strncmp(str1, str2, 3) == 0);
167 ASSERT_ZERO_LABEL(strd);
168 ASSERT_ZERO_LABEL(strd[0]);
169 ASSERT_ZERO_LABEL(strd[1]);
170 ASSERT_ZERO_LABEL(strd[2]);
171}
172
173void test_strncmp() {
174 char str1[] = "str1", str2[] = "str2";
175 dfsan_set_label(i_label, &str1[3], 1);
176 dfsan_set_label(j_label, &str2[3], 1);
177
178 int rv = strncmp(str1, str2, sizeof(str1));
179 assert(rv < 0);
180#ifdef STRICT_DATA_DEPENDENCIES
181 ASSERT_ZERO_LABEL(rv);
182#else
183 ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
184#endif
185
186 rv = strncmp(str1, str2, 3);
187 assert(rv == 0);
188 ASSERT_ZERO_LABEL(rv);
189}
190
191void test_strcasecmp() {
192 char str1[] = "str1", str2[] = "str2", str3[] = "Str1";
193 dfsan_set_label(i_label, &str1[3], 1);
194 dfsan_set_label(j_label, &str2[3], 1);
195 dfsan_set_label(j_label, &str3[2], 1);
196
197 int rv = strcasecmp(str1, str2);
198 assert(rv < 0);
199#ifdef STRICT_DATA_DEPENDENCIES
200 ASSERT_ZERO_LABEL(rv);
201#else
202 ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
203#endif
204
205 rv = strcasecmp(str1, str3);
206 assert(rv == 0);
207#ifdef STRICT_DATA_DEPENDENCIES
208 ASSERT_ZERO_LABEL(rv);
209#else
210 ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
211#endif
212}
213
214void test_strncasecmp() {
215 char str1[] = "Str1", str2[] = "str2";
216 dfsan_set_label(i_label, &str1[3], 1);
217 dfsan_set_label(j_label, &str2[3], 1);
218
219 int rv = strncasecmp(str1, str2, sizeof(str1));
220 assert(rv < 0);
221#ifdef STRICT_DATA_DEPENDENCIES
222 ASSERT_ZERO_LABEL(rv);
223#else
224 ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
225#endif
226
227 rv = strncasecmp(str1, str2, 3);
228 assert(rv == 0);
229 ASSERT_ZERO_LABEL(rv);
230}
231
232void test_strchr() {
233 char str1[] = "str1";
234 dfsan_set_label(i_label, &str1[3], 1);
235
236 char *crv = strchr(str1, 'r');
237 assert(crv == &str1[2]);
238 ASSERT_ZERO_LABEL(crv);
239
240 crv = strchr(str1, '1');
241 assert(crv == &str1[3]);
242#ifdef STRICT_DATA_DEPENDENCIES
243 ASSERT_ZERO_LABEL(crv);
244#else
245 ASSERT_LABEL(crv, i_label);
246#endif
247
248 crv = strchr(str1, 'x');
249 assert(!crv);
250#ifdef STRICT_DATA_DEPENDENCIES
251 ASSERT_ZERO_LABEL(crv);
252#else
253 ASSERT_LABEL(crv, i_label);
254#endif
255}
256
257void test_calloc() {
258 // With any luck this sequence of calls will cause calloc to return the same
259 // pointer both times. This is probably the best we can do to test this
260 // function.
92a42be0 261 char *crv = (char *) calloc(4096, 1);
1a4d82fc
JJ
262 ASSERT_ZERO_LABEL(crv[0]);
263 dfsan_set_label(i_label, crv, 100);
264 free(crv);
265
92a42be0 266 crv = (char *) calloc(4096, 1);
1a4d82fc
JJ
267 ASSERT_ZERO_LABEL(crv[0]);
268 free(crv);
269}
270
271void test_read() {
272 char buf[16];
273 dfsan_set_label(i_label, buf, 1);
274 dfsan_set_label(j_label, buf + 15, 1);
275
276 ASSERT_LABEL(buf[0], i_label);
277 ASSERT_LABEL(buf[15], j_label);
278
279 int fd = open("/dev/zero", O_RDONLY);
280 int rv = read(fd, buf, sizeof(buf));
281 assert(rv == sizeof(buf));
282 ASSERT_ZERO_LABEL(rv);
283 ASSERT_ZERO_LABEL(buf[0]);
284 ASSERT_ZERO_LABEL(buf[15]);
285 close(fd);
286}
287
288void test_pread() {
289 char buf[16];
290 dfsan_set_label(i_label, buf, 1);
291 dfsan_set_label(j_label, buf + 15, 1);
292
293 ASSERT_LABEL(buf[0], i_label);
294 ASSERT_LABEL(buf[15], j_label);
295
296 int fd = open("/bin/sh", O_RDONLY);
297 int rv = pread(fd, buf, sizeof(buf), 0);
298 assert(rv == sizeof(buf));
299 ASSERT_ZERO_LABEL(rv);
300 ASSERT_ZERO_LABEL(buf[0]);
301 ASSERT_ZERO_LABEL(buf[15]);
302 close(fd);
303}
304
305void test_dlopen() {
306 void *map = dlopen(NULL, RTLD_NOW);
307 assert(map);
308 ASSERT_ZERO_LABEL(map);
309 dlclose(map);
310 map = dlopen("/nonexistent", RTLD_NOW);
311 assert(!map);
312 ASSERT_ZERO_LABEL(map);
313}
314
315void test_clock_gettime() {
316 struct timespec tp;
317 dfsan_set_label(j_label, ((char *)&tp) + 3, 1);
318 int t = clock_gettime(CLOCK_REALTIME, &tp);
319 assert(t == 0);
320 ASSERT_ZERO_LABEL(t);
321 ASSERT_ZERO_LABEL(((char *)&tp)[3]);
322}
323
324void test_ctime_r() {
325 char *buf = (char*) malloc(64);
326 time_t t = 0;
327
328 char *ret = ctime_r(&t, buf);
329 ASSERT_ZERO_LABEL(ret);
330 assert(buf == ret);
331 ASSERT_READ_ZERO_LABEL(buf, strlen(buf) + 1);
332
333 dfsan_set_label(i_label, &t, sizeof(t));
334 ret = ctime_r(&t, buf);
335 ASSERT_ZERO_LABEL(ret);
336 ASSERT_READ_LABEL(buf, strlen(buf) + 1, i_label);
337
338 t = 0;
339 dfsan_set_label(j_label, &buf, sizeof(&buf));
340 ret = ctime_r(&t, buf);
341 ASSERT_LABEL(ret, j_label);
342 ASSERT_READ_ZERO_LABEL(buf, strlen(buf) + 1);
343}
344
345static int write_callback_count = 0;
346static int last_fd;
92a42be0 347static const unsigned char *last_buf;
1a4d82fc
JJ
348static size_t last_count;
349
350void write_callback(int fd, const void *buf, size_t count) {
351 write_callback_count++;
352
353 last_fd = fd;
92a42be0 354 last_buf = (const unsigned char*) buf;
1a4d82fc
JJ
355 last_count = count;
356}
357
358void test_dfsan_set_write_callback() {
359 char buf[] = "Sample chars";
360 int buf_len = strlen(buf);
361
362 int fd = open("/dev/null", O_WRONLY);
363
364 dfsan_set_write_callback(write_callback);
365
366 write_callback_count = 0;
367
368 // Callback should be invoked on every call to write().
369 int res = write(fd, buf, buf_len);
370 assert(write_callback_count == 1);
371 ASSERT_READ_ZERO_LABEL(&res, sizeof(res));
372 ASSERT_READ_ZERO_LABEL(&last_fd, sizeof(last_fd));
373 ASSERT_READ_ZERO_LABEL(last_buf, sizeof(last_buf));
374 ASSERT_READ_ZERO_LABEL(&last_count, sizeof(last_count));
375
376 // Add a label to write() arguments. Check that the labels are readable from
377 // the values passed to the callback.
378 dfsan_set_label(i_label, &fd, sizeof(fd));
379 dfsan_set_label(j_label, &(buf[3]), 1);
380 dfsan_set_label(k_label, &buf_len, sizeof(buf_len));
92a42be0 381
1a4d82fc
JJ
382 res = write(fd, buf, buf_len);
383 assert(write_callback_count == 2);
384 ASSERT_READ_ZERO_LABEL(&res, sizeof(res));
385 ASSERT_READ_LABEL(&last_fd, sizeof(last_fd), i_label);
386 ASSERT_READ_LABEL(&last_buf[3], sizeof(last_buf[3]), j_label);
387 ASSERT_READ_LABEL(last_buf, sizeof(last_buf), j_label);
388 ASSERT_READ_LABEL(&last_count, sizeof(last_count), k_label);
389
390 dfsan_set_write_callback(NULL);
391}
392
393void test_fgets() {
394 char *buf = (char*) malloc(128);
395 FILE *f = fopen("/etc/passwd", "r");
396 dfsan_set_label(j_label, buf, 1);
397 char *ret = fgets(buf, sizeof(buf), f);
398 assert(ret == buf);
399 ASSERT_ZERO_LABEL(ret);
400 ASSERT_READ_ZERO_LABEL(buf, 128);
401 dfsan_set_label(j_label, &buf, sizeof(&buf));
402 ret = fgets(buf, sizeof(buf), f);
403 ASSERT_LABEL(ret, j_label);
404 fclose(f);
405}
406
407void test_getcwd() {
408 char buf[1024];
409 char *ptr = buf;
410 dfsan_set_label(i_label, buf + 2, 2);
411 char* ret = getcwd(buf, sizeof(buf));
412 assert(ret == buf);
413 assert(ret[0] == '/');
414 ASSERT_READ_ZERO_LABEL(buf + 2, 2);
415 dfsan_set_label(i_label, &ptr, sizeof(ptr));
416 ret = getcwd(ptr, sizeof(buf));
417 ASSERT_LABEL(ret, i_label);
418}
419
420void test_get_current_dir_name() {
421 char* ret = get_current_dir_name();
422 assert(ret);
423 assert(ret[0] == '/');
424 ASSERT_READ_ZERO_LABEL(ret, strlen(ret) + 1);
425}
426
427void test_gethostname() {
428 char buf[1024];
429 dfsan_set_label(i_label, buf + 2, 2);
430 assert(gethostname(buf, sizeof(buf)) == 0);
431 ASSERT_READ_ZERO_LABEL(buf + 2, 2);
432}
433
434void test_getrlimit() {
435 struct rlimit rlim;
436 dfsan_set_label(i_label, &rlim, sizeof(rlim));
437 assert(getrlimit(RLIMIT_CPU, &rlim) == 0);
438 ASSERT_READ_ZERO_LABEL(&rlim, sizeof(rlim));
439}
440
441void test_getrusage() {
442 struct rusage usage;
443 dfsan_set_label(i_label, &usage, sizeof(usage));
444 assert(getrusage(RUSAGE_SELF, &usage) == 0);
445 ASSERT_READ_ZERO_LABEL(&usage, sizeof(usage));
446}
447
448void test_strcpy() {
449 char src[] = "hello world";
450 char dst[sizeof(src) + 2];
451 dfsan_set_label(0, src, sizeof(src));
452 dfsan_set_label(0, dst, sizeof(dst));
453 dfsan_set_label(i_label, src + 2, 1);
454 dfsan_set_label(j_label, src + 3, 1);
455 dfsan_set_label(j_label, dst + 4, 1);
456 dfsan_set_label(i_label, dst + 12, 1);
457 char *ret = strcpy(dst, src);
458 assert(ret == dst);
459 assert(strcmp(src, dst) == 0);
460 for (int i = 0; i < strlen(src) + 1; ++i) {
461 assert(dfsan_get_label(dst[i]) == dfsan_get_label(src[i]));
462 }
463 // Note: if strlen(src) + 1 were used instead to compute the first untouched
464 // byte of dest, the label would be I|J. This is because strlen() might
465 // return a non-zero label, and because by default pointer labels are not
466 // ignored on loads.
467 ASSERT_LABEL(dst[12], i_label);
468}
469
470void test_strtol() {
471 char buf[] = "1234578910";
472 char *endptr = NULL;
473 dfsan_set_label(i_label, buf + 1, 1);
474 dfsan_set_label(j_label, buf + 10, 1);
475 long int ret = strtol(buf, &endptr, 10);
476 assert(ret == 1234578910);
477 assert(endptr == buf + 10);
478 ASSERT_LABEL(ret, i_j_label);
479}
480
481void test_strtoll() {
482 char buf[] = "1234578910 ";
483 char *endptr = NULL;
484 dfsan_set_label(i_label, buf + 1, 1);
485 dfsan_set_label(j_label, buf + 2, 1);
486 long long int ret = strtoll(buf, &endptr, 10);
487 assert(ret == 1234578910);
488 assert(endptr == buf + 10);
489 ASSERT_LABEL(ret, i_j_label);
490}
491
492void test_strtoul() {
493 char buf[] = "0xffffffffffffaa";
494 char *endptr = NULL;
495 dfsan_set_label(i_label, buf + 1, 1);
496 dfsan_set_label(j_label, buf + 2, 1);
497 long unsigned int ret = strtol(buf, &endptr, 16);
498 assert(ret == 72057594037927850);
499 assert(endptr == buf + 16);
500 ASSERT_LABEL(ret, i_j_label);
501}
502
503void test_strtoull() {
504 char buf[] = "0xffffffffffffffaa";
505 char *endptr = NULL;
506 dfsan_set_label(i_label, buf + 1, 1);
507 dfsan_set_label(j_label, buf + 2, 1);
508 long long unsigned int ret = strtoull(buf, &endptr, 16);
509 assert(ret == 0xffffffffffffffaa);
510 assert(endptr == buf + 18);
511 ASSERT_LABEL(ret, i_j_label);
512}
513
514void test_strtod() {
515 char buf[] = "12345.76 foo";
516 char *endptr = NULL;
517 dfsan_set_label(i_label, buf + 1, 1);
518 dfsan_set_label(j_label, buf + 6, 1);
519 double ret = strtod(buf, &endptr);
520 assert(ret == 12345.76);
521 assert(endptr == buf + 8);
522 ASSERT_LABEL(ret, i_j_label);
523}
524
525void test_time() {
526 time_t t = 0;
527 dfsan_set_label(i_label, &t, 1);
528 time_t ret = time(&t);
529 assert(ret == t);
530 assert(ret > 0);
531 ASSERT_ZERO_LABEL(t);
532}
533
534void test_inet_pton() {
535 char addr4[] = "127.0.0.1";
536 dfsan_set_label(i_label, addr4 + 3, 1);
537 struct in_addr in4;
538 int ret4 = inet_pton(AF_INET, addr4, &in4);
539 assert(ret4 == 1);
540 ASSERT_READ_LABEL(&in4, sizeof(in4), i_label);
5bcae85e 541 assert(in4.s_addr == htonl(0x7f000001));
1a4d82fc
JJ
542
543 char addr6[] = "::1";
544 dfsan_set_label(j_label, addr6 + 3, 1);
545 struct in6_addr in6;
546 int ret6 = inet_pton(AF_INET6, addr6, &in6);
547 assert(ret6 == 1);
548 ASSERT_READ_LABEL(((char *) &in6) + sizeof(in6) - 1, 1, j_label);
549}
550
551void test_localtime_r() {
552 time_t t0 = 1384800998;
553 struct tm t1;
554 dfsan_set_label(i_label, &t0, sizeof(t0));
555 struct tm* ret = localtime_r(&t0, &t1);
556 assert(ret == &t1);
557 assert(t1.tm_min == 56);
558 ASSERT_LABEL(t1.tm_mon, i_label);
559}
560
561void test_getpwuid_r() {
562 struct passwd pwd;
563 char buf[1024];
564 struct passwd *result;
565
566 dfsan_set_label(i_label, &pwd, 4);
567 int ret = getpwuid_r(0, &pwd, buf, sizeof(buf), &result);
568 assert(ret == 0);
569 assert(strcmp(pwd.pw_name, "root") == 0);
570 assert(result == &pwd);
571 ASSERT_READ_ZERO_LABEL(&pwd, 4);
572}
573
574void test_poll() {
575 struct pollfd fd;
576 fd.fd = 0;
577 fd.events = POLLIN;
578 dfsan_set_label(i_label, &fd.revents, sizeof(fd.revents));
579 int ret = poll(&fd, 1, 1);
580 ASSERT_ZERO_LABEL(fd.revents);
581 assert(ret >= 0);
582}
583
584void test_select() {
585 struct timeval t;
586 fd_set fds;
587 t.tv_sec = 2;
588 FD_SET(0, &fds);
589 dfsan_set_label(i_label, &fds, sizeof(fds));
590 dfsan_set_label(j_label, &t, sizeof(t));
591 int ret = select(1, &fds, NULL, NULL, &t);
592 assert(ret >= 0);
593 ASSERT_ZERO_LABEL(t.tv_sec);
594 ASSERT_READ_ZERO_LABEL(&fds, sizeof(fds));
595}
596
597void test_sched_getaffinity() {
598 cpu_set_t mask;
599 dfsan_set_label(j_label, &mask, 1);
600 int ret = sched_getaffinity(0, sizeof(mask), &mask);
601 assert(ret == 0);
602 ASSERT_READ_ZERO_LABEL(&mask, sizeof(mask));
603}
604
605void test_sigemptyset() {
606 sigset_t set;
607 dfsan_set_label(j_label, &set, 1);
608 int ret = sigemptyset(&set);
609 assert(ret == 0);
610 ASSERT_READ_ZERO_LABEL(&set, sizeof(set));
611}
612
613void test_sigaction() {
614 struct sigaction oldact;
615 dfsan_set_label(j_label, &oldact, 1);
616 int ret = sigaction(SIGUSR1, NULL, &oldact);
617 assert(ret == 0);
618 ASSERT_READ_ZERO_LABEL(&oldact, sizeof(oldact));
619}
620
621void test_gettimeofday() {
622 struct timeval tv;
623 struct timezone tz;
624 dfsan_set_label(i_label, &tv, sizeof(tv));
625 dfsan_set_label(j_label, &tz, sizeof(tz));
626 int ret = gettimeofday(&tv, &tz);
627 assert(ret == 0);
628 ASSERT_READ_ZERO_LABEL(&tv, sizeof(tv));
629 ASSERT_READ_ZERO_LABEL(&tz, sizeof(tz));
630}
631
632void *pthread_create_test_cb(void *p) {
633 assert(p == (void *)1);
634 ASSERT_ZERO_LABEL(p);
635 return (void *)2;
636}
637
638void test_pthread_create() {
639 pthread_t pt;
640 pthread_create(&pt, 0, pthread_create_test_cb, (void *)1);
641 void *cbrv;
642 pthread_join(pt, &cbrv);
643 assert(cbrv == (void *)2);
644}
645
646int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
647 void *data) {
648 assert(data == (void *)3);
649 ASSERT_ZERO_LABEL(info);
650 ASSERT_ZERO_LABEL(size);
651 ASSERT_ZERO_LABEL(data);
652 return 0;
653}
654
655void test_dl_iterate_phdr() {
656 dl_iterate_phdr(dl_iterate_phdr_test_cb, (void *)3);
657}
658
659void test_strrchr() {
660 char str1[] = "str1str1";
661 dfsan_set_label(i_label, &str1[7], 1);
662
663 char *rv = strrchr(str1, 'r');
664 assert(rv == &str1[6]);
665#ifdef STRICT_DATA_DEPENDENCIES
666 ASSERT_ZERO_LABEL(rv);
667#else
668 ASSERT_LABEL(rv, i_label);
669#endif
670}
671
672void test_strstr() {
673 char str1[] = "str1str1";
674 dfsan_set_label(i_label, &str1[3], 1);
675 dfsan_set_label(j_label, &str1[5], 1);
676
677 char *rv = strstr(str1, "1s");
678 assert(rv == &str1[3]);
679#ifdef STRICT_DATA_DEPENDENCIES
680 ASSERT_ZERO_LABEL(rv);
681#else
682 ASSERT_LABEL(rv, i_label);
683#endif
684
685 rv = strstr(str1, "2s");
686 assert(rv == NULL);
687#ifdef STRICT_DATA_DEPENDENCIES
688 ASSERT_ZERO_LABEL(rv);
689#else
690 ASSERT_LABEL(rv, i_j_label);
691#endif
692}
693
694void test_memchr() {
695 char str1[] = "str1";
696 dfsan_set_label(i_label, &str1[3], 1);
697 dfsan_set_label(j_label, &str1[4], 1);
698
92a42be0 699 char *crv = (char *) memchr(str1, 'r', sizeof(str1));
1a4d82fc
JJ
700 assert(crv == &str1[2]);
701 ASSERT_ZERO_LABEL(crv);
702
92a42be0 703 crv = (char *) memchr(str1, '1', sizeof(str1));
1a4d82fc
JJ
704 assert(crv == &str1[3]);
705#ifdef STRICT_DATA_DEPENDENCIES
706 ASSERT_ZERO_LABEL(crv);
707#else
708 ASSERT_LABEL(crv, i_label);
709#endif
710
92a42be0 711 crv = (char *) memchr(str1, 'x', sizeof(str1));
1a4d82fc
JJ
712 assert(!crv);
713#ifdef STRICT_DATA_DEPENDENCIES
714 ASSERT_ZERO_LABEL(crv);
715#else
716 ASSERT_LABEL(crv, i_j_label);
717#endif
718}
719
720void alarm_handler(int unused) {
721 ;
722}
723
724void test_nanosleep() {
725 struct timespec req, rem;
726 req.tv_sec = 1;
727 req.tv_nsec = 0;
728 dfsan_set_label(i_label, &rem, sizeof(rem));
729
730 // non interrupted
731 int rv = nanosleep(&req, &rem);
732 assert(rv == 0);
733 ASSERT_ZERO_LABEL(rv);
734 ASSERT_READ_LABEL(&rem, 1, i_label);
735
736 // interrupted by an alarm
737 signal(SIGALRM, alarm_handler);
738 req.tv_sec = 3;
739 alarm(1);
740 rv = nanosleep(&req, &rem);
741 assert(rv == -1);
742 ASSERT_ZERO_LABEL(rv);
743 ASSERT_READ_ZERO_LABEL(&rem, sizeof(rem));
744}
745
746void test_socketpair() {
747 int fd[2];
748
749 dfsan_set_label(i_label, fd, sizeof(fd));
750 int rv = socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
751 assert(rv == 0);
752 ASSERT_ZERO_LABEL(rv);
753 ASSERT_READ_ZERO_LABEL(fd, sizeof(fd));
754}
755
756void test_write() {
757 int fd = open("/dev/null", O_WRONLY);
758
759 char buf[] = "a string";
760 int len = strlen(buf);
761
762 // The result of a write always unlabeled.
763 int res = write(fd, buf, len);
764 assert(res > 0);
765 ASSERT_ZERO_LABEL(res);
766
767 // Label all arguments to write().
768 dfsan_set_label(i_label, &(buf[3]), 1);
769 dfsan_set_label(j_label, &fd, sizeof(fd));
770 dfsan_set_label(i_label, &len, sizeof(len));
771
772 // The value returned by write() should have no label.
773 res = write(fd, buf, len);
774 ASSERT_ZERO_LABEL(res);
775
776 close(fd);
777}
778
92a42be0
SL
779template <class T>
780void test_sprintf_chunk(const char* expected, const char* format, T arg) {
781 char buf[512];
782 memset(buf, 'a', sizeof(buf));
783
784 char padded_expected[512];
785 strcpy(padded_expected, "foo ");
786 strcat(padded_expected, expected);
787 strcat(padded_expected, " bar");
788
789 char padded_format[512];
790 strcpy(padded_format, "foo ");
791 strcat(padded_format, format);
792 strcat(padded_format, " bar");
793
794 // Non labelled arg.
795 assert(sprintf(buf, padded_format, arg) == strlen(padded_expected));
796 assert(strcmp(buf, padded_expected) == 0);
797 ASSERT_READ_LABEL(buf, strlen(padded_expected), 0);
798 memset(buf, 'a', sizeof(buf));
799
800 // Labelled arg.
801 dfsan_set_label(i_label, &arg, sizeof(arg));
802 assert(sprintf(buf, padded_format, arg) == strlen(padded_expected));
803 assert(strcmp(buf, padded_expected) == 0);
804 ASSERT_READ_LABEL(buf, 4, 0);
805 ASSERT_READ_LABEL(buf + 4, strlen(padded_expected) - 8, i_label);
806 ASSERT_READ_LABEL(buf + (strlen(padded_expected) - 4), 4, 0);
807}
808
809void test_sprintf() {
810 char buf[2048];
811 memset(buf, 'a', sizeof(buf));
812
813 // Test formatting (no conversion specifier).
814 assert(sprintf(buf, "Hello world!") == 12);
815 assert(strcmp(buf, "Hello world!") == 0);
816 ASSERT_READ_LABEL(buf, sizeof(buf), 0);
817
818 // Test for extra arguments.
819 assert(sprintf(buf, "Hello world!", 42, "hello") == 12);
820 assert(strcmp(buf, "Hello world!") == 0);
821 ASSERT_READ_LABEL(buf, sizeof(buf), 0);
822
823 // Test formatting & label propagation (multiple conversion specifiers): %s,
824 // %d, %n, %f, and %%.
825 const char* s = "world";
826 int m = 8;
827 int d = 27;
828 dfsan_set_label(k_label, (void *) (s + 1), 2);
829 dfsan_set_label(i_label, &m, sizeof(m));
830 dfsan_set_label(j_label, &d, sizeof(d));
831 int n;
832 int r = sprintf(buf, "hello %s, %-d/%d/%d %f %% %n%d", s, 2014, m, d,
833 12345.6781234, &n, 1000);
834 assert(r == 42);
835 assert(strcmp(buf, "hello world, 2014/8/27 12345.678123 % 1000") == 0);
836 ASSERT_READ_LABEL(buf, 7, 0);
837 ASSERT_READ_LABEL(buf + 7, 2, k_label);
838 ASSERT_READ_LABEL(buf + 9, 9, 0);
839 ASSERT_READ_LABEL(buf + 18, 1, i_label);
840 ASSERT_READ_LABEL(buf + 19, 1, 0);
841 ASSERT_READ_LABEL(buf + 20, 2, j_label);
842 ASSERT_READ_LABEL(buf + 22, 15, 0);
843 ASSERT_LABEL(r, 0);
844 assert(n == 38);
845
846 // Test formatting & label propagation (single conversion specifier, with
847 // additional length and precision modifiers).
848 test_sprintf_chunk("-559038737", "%d", 0xdeadbeef);
849 test_sprintf_chunk("3735928559", "%u", 0xdeadbeef);
850 test_sprintf_chunk("12345", "%i", 12345);
851 test_sprintf_chunk("751", "%o", 0751);
852 test_sprintf_chunk("babe", "%x", 0xbabe);
853 test_sprintf_chunk("0000BABE", "%.8X", 0xbabe);
854 test_sprintf_chunk("-17", "%hhd", 0xdeadbeef);
855 test_sprintf_chunk("-16657", "%hd", 0xdeadbeef);
856 test_sprintf_chunk("deadbeefdeadbeef", "%lx", 0xdeadbeefdeadbeef);
857 test_sprintf_chunk("0xdeadbeefdeadbeef", "%p",
858 (void *) 0xdeadbeefdeadbeef);
859 test_sprintf_chunk("18446744073709551615", "%ju", (intmax_t) -1);
860 test_sprintf_chunk("18446744073709551615", "%zu", (size_t) -1);
861 test_sprintf_chunk("18446744073709551615", "%tu", (size_t) -1);
862
863 test_sprintf_chunk("0x1.f9acffa7eb6bfp-4", "%a", 0.123456);
864 test_sprintf_chunk("0X1.F9ACFFA7EB6BFP-4", "%A", 0.123456);
865 test_sprintf_chunk("0.12346", "%.5f", 0.123456);
866 test_sprintf_chunk("0.123456", "%g", 0.123456);
867 test_sprintf_chunk("1.234560e-01", "%e", 0.123456);
868 test_sprintf_chunk("1.234560E-01", "%E", 0.123456);
869 test_sprintf_chunk("0.1234567891234560", "%.16Lf",
870 (long double) 0.123456789123456);
871
872 test_sprintf_chunk("z", "%c", 'z');
873
874 // %n, %s, %d, %f, and %% already tested
875
876 // Test formatting with width passed as an argument.
877 r = sprintf(buf, "hi %*d my %*s friend %.*f", 3, 1, 6, "dear", 4, 3.14159265359);
878 assert(r == 30);
879 assert(strcmp(buf, "hi 1 my dear friend 3.1416") == 0);
880}
881
882void test_snprintf() {
883 char buf[2048];
884 memset(buf, 'a', sizeof(buf));
885 dfsan_set_label(0, buf, sizeof(buf));
886 const char* s = "world";
887 int y = 2014;
888 int m = 8;
889 int d = 27;
890 dfsan_set_label(k_label, (void *) (s + 1), 2);
891 dfsan_set_label(i_label, &y, sizeof(y));
892 dfsan_set_label(j_label, &m, sizeof(m));
893 int r = snprintf(buf, 19, "hello %s, %-d/%d/%d %f", s, y, m, d,
894 12345.6781234);
895 // The return value is the number of bytes that would have been written to
896 // the final string if enough space had been available.
897 assert(r == 35);
898 assert(memcmp(buf, "hello world, 2014/", 19) == 0);
899 ASSERT_READ_LABEL(buf, 7, 0);
900 ASSERT_READ_LABEL(buf + 7, 2, k_label);
901 ASSERT_READ_LABEL(buf + 9, 4, 0);
902 ASSERT_READ_LABEL(buf + 13, 4, i_label);
903 ASSERT_READ_LABEL(buf + 17, 2, 0);
904 ASSERT_LABEL(r, 0);
905}
906
1a4d82fc
JJ
907int main(void) {
908 i_label = dfsan_create_label("i", 0);
909 j_label = dfsan_create_label("j", 0);
910 k_label = dfsan_create_label("k", 0);
911 i_j_label = dfsan_union(i_label, j_label);
912
913 test_calloc();
914 test_clock_gettime();
915 test_ctime_r();
916 test_dfsan_set_write_callback();
917 test_dl_iterate_phdr();
918 test_dlopen();
919 test_fgets();
920 test_fstat();
921 test_get_current_dir_name();
922 test_getcwd();
923 test_gethostname();
924 test_getpwuid_r();
925 test_getrlimit();
926 test_getrusage();
927 test_gettimeofday();
928 test_inet_pton();
929 test_localtime_r();
930 test_memchr();
931 test_memcmp();
932 test_memcpy();
933 test_memset();
934 test_nanosleep();
935 test_poll();
936 test_pread();
937 test_pthread_create();
938 test_read();
939 test_sched_getaffinity();
940 test_select();
941 test_sigaction();
942 test_sigemptyset();
92a42be0 943 test_snprintf();
1a4d82fc 944 test_socketpair();
92a42be0 945 test_sprintf();
1a4d82fc
JJ
946 test_stat();
947 test_strcasecmp();
948 test_strchr();
949 test_strcmp();
950 test_strcpy();
951 test_strdup();
952 test_strlen();
953 test_strncasecmp();
954 test_strncmp();
955 test_strncpy();
956 test_strrchr();
957 test_strstr();
958 test_strtod();
959 test_strtol();
960 test_strtoll();
961 test_strtoul();
962 test_strtoull();
963 test_time();
964 test_write();
965}