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