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