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