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/epoll.h>
26 #include <sys/resource.h>
27 #include <sys/select.h>
28 #include <sys/socket.h>
29 #include <sys/stat.h>
30 #include <sys/time.h>
31 #include <sys/types.h>
32 #include <time.h>
33 #include <unistd.h>
34 
35 dfsan_label i_label = 0;
36 dfsan_label j_label = 0;
37 dfsan_label k_label = 0;
38 dfsan_label i_j_label = 0;
39 
40 #define ASSERT_ZERO_LABEL(data) \
41   assert(0 == dfsan_get_label((long) (data)))
42 
43 #define ASSERT_READ_ZERO_LABEL(ptr, size) \
44   assert(0 == dfsan_read_label(ptr, size))
45 
46 #define ASSERT_LABEL(data, label) \
47   assert(label == dfsan_get_label((long) (data)))
48 
49 #define ASSERT_READ_LABEL(ptr, size, label) \
50   assert(label == dfsan_read_label(ptr, size))
51 
52 void test_stat() {
53   int i = 1;
54   dfsan_set_label(i_label, &i, sizeof(i));
55 
56   struct stat s;
57   s.st_dev = i;
58   assert(0 == stat("/", &s));
59   ASSERT_ZERO_LABEL(s.st_dev);
60 
61   s.st_dev = i;
62   assert(-1 == stat("/nonexistent", &s));
63   ASSERT_LABEL(s.st_dev, i_label);
64 }
65 
66 void test_fstat() {
67   int i = 1;
68   dfsan_set_label(i_label, &i, sizeof(i));
69 
70   struct stat s;
71   int fd = open("/dev/zero", O_RDONLY);
72   s.st_dev = i;
73   int rv = fstat(fd, &s);
74   assert(0 == rv);
75   ASSERT_ZERO_LABEL(s.st_dev);
76 }
77 
78 void test_memcmp() {
79   char str1[] = "str1", str2[] = "str2";
80   dfsan_set_label(i_label, &str1[3], 1);
81   dfsan_set_label(j_label, &str2[3], 1);
82 
83   int rv = memcmp(str1, str2, sizeof(str1));
84   assert(rv < 0);
85 #ifdef STRICT_DATA_DEPENDENCIES
86   ASSERT_ZERO_LABEL(rv);
87 #else
88   ASSERT_LABEL(rv, i_j_label);
89 #endif
90 }
91 
92 void test_bcmp() {
93   char str1[] = "str1", str2[] = "str2";
94   dfsan_set_label(i_label, &str1[3], 1);
95   dfsan_set_label(j_label, &str2[3], 1);
96 
97   int rv = bcmp(str1, str2, sizeof(str1));
98   assert(rv != 0);
99 #ifdef STRICT_DATA_DEPENDENCIES
100   ASSERT_ZERO_LABEL(rv);
101 #else
102   ASSERT_LABEL(rv, i_j_label);
103 #endif
104 
105   rv = bcmp(str1, str2, sizeof(str1) - 2);
106   assert(rv == 0);
107   ASSERT_ZERO_LABEL(rv);
108 }
109 
110 void test_memcpy() {
111   char str1[] = "str1";
112   char str2[sizeof(str1)];
113   dfsan_set_label(i_label, &str1[3], 1);
114 
115   ASSERT_ZERO_LABEL(memcpy(str2, str1, sizeof(str1)));
116   assert(0 == memcmp(str2, str1, sizeof(str1)));
117   ASSERT_ZERO_LABEL(str2[0]);
118   ASSERT_LABEL(str2[3], i_label);
119 }
120 
121 void test_memset() {
122   char buf[8];
123   int j = 'a';
124   dfsan_set_label(j_label, &j, sizeof(j));
125 
126   ASSERT_ZERO_LABEL(memset(&buf, j, sizeof(buf)));
127   for (int i = 0; i < 8; ++i) {
128     ASSERT_LABEL(buf[i], j_label);
129     assert(buf[i] == 'a');
130   }
131 }
132 
133 void test_strcmp() {
134   char str1[] = "str1", str2[] = "str2";
135   dfsan_set_label(i_label, &str1[3], 1);
136   dfsan_set_label(j_label, &str2[3], 1);
137 
138   int rv = strcmp(str1, str2);
139   assert(rv < 0);
140 #ifdef STRICT_DATA_DEPENDENCIES
141   ASSERT_ZERO_LABEL(rv);
142 #else
143   ASSERT_LABEL(rv, i_j_label);
144 #endif
145 }
146 
147 void test_strlen() {
148   char str1[] = "str1";
149   dfsan_set_label(i_label, &str1[3], 1);
150 
151   int rv = strlen(str1);
152   assert(rv == 4);
153 #ifdef STRICT_DATA_DEPENDENCIES
154   ASSERT_ZERO_LABEL(rv);
155 #else
156   ASSERT_LABEL(rv, i_label);
157 #endif
158 }
159 
160 void test_strdup() {
161   char str1[] = "str1";
162   dfsan_set_label(i_label, &str1[3], 1);
163 
164   char *strd = strdup(str1);
165   ASSERT_ZERO_LABEL(strd[0]);
166   ASSERT_LABEL(strd[3], i_label);
167   free(strd);
168 }
169 
170 void test_strncpy() {
171   char str1[] = "str1";
172   char str2[sizeof(str1)];
173   dfsan_set_label(i_label, &str1[3], 1);
174 
175   char *strd = strncpy(str2, str1, 5);
176   assert(strd == str2);
177   assert(strcmp(str1, str2) == 0);
178   ASSERT_ZERO_LABEL(strd);
179   ASSERT_ZERO_LABEL(strd[0]);
180   ASSERT_ZERO_LABEL(strd[1]);
181   ASSERT_ZERO_LABEL(strd[2]);
182   ASSERT_LABEL(strd[3], i_label);
183 
184   strd = strncpy(str2, str1, 3);
185   assert(strd == str2);
186   assert(strncmp(str1, str2, 3) == 0);
187   ASSERT_ZERO_LABEL(strd);
188   ASSERT_ZERO_LABEL(strd[0]);
189   ASSERT_ZERO_LABEL(strd[1]);
190   ASSERT_ZERO_LABEL(strd[2]);
191 }
192 
193 void test_strncmp() {
194   char str1[] = "str1", str2[] = "str2";
195   dfsan_set_label(i_label, &str1[3], 1);
196   dfsan_set_label(j_label, &str2[3], 1);
197 
198   int rv = strncmp(str1, str2, sizeof(str1));
199   assert(rv < 0);
200 #ifdef STRICT_DATA_DEPENDENCIES
201   ASSERT_ZERO_LABEL(rv);
202 #else
203   ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
204 #endif
205 
206   rv = strncmp(str1, str2, 3);
207   assert(rv == 0);
208   ASSERT_ZERO_LABEL(rv);
209 }
210 
211 void test_strcasecmp() {
212   char str1[] = "str1", str2[] = "str2", str3[] = "Str1";
213   dfsan_set_label(i_label, &str1[3], 1);
214   dfsan_set_label(j_label, &str2[3], 1);
215   dfsan_set_label(j_label, &str3[2], 1);
216 
217   int rv = strcasecmp(str1, str2);
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 = strcasecmp(str1, str3);
226   assert(rv == 0);
227 #ifdef STRICT_DATA_DEPENDENCIES
228   ASSERT_ZERO_LABEL(rv);
229 #else
230   ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
231 #endif
232 
233   char s1[] = "AbZ";
234   char s2[] = "aBy";
235   dfsan_set_label(i_label, &s1[2], 1);
236   dfsan_set_label(j_label, &s2[2], 1);
237 
238   rv = strcasecmp(s1, s2);
239   assert(rv > 0); // 'Z' > 'y'
240 #ifdef STRICT_DATA_DEPENDENCIES
241   ASSERT_ZERO_LABEL(rv);
242 #else
243   ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
244 #endif
245 }
246 
247 void test_strncasecmp() {
248   char str1[] = "Str1", str2[] = "str2";
249   dfsan_set_label(i_label, &str1[3], 1);
250   dfsan_set_label(j_label, &str2[3], 1);
251 
252   int rv = strncasecmp(str1, str2, sizeof(str1));
253   assert(rv < 0);
254 #ifdef STRICT_DATA_DEPENDENCIES
255   ASSERT_ZERO_LABEL(rv);
256 #else
257   ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
258 #endif
259 
260   rv = strncasecmp(str1, str2, 3);
261   assert(rv == 0);
262   ASSERT_ZERO_LABEL(rv);
263 
264   char s1[] = "AbZ";
265   char s2[] = "aBy";
266   dfsan_set_label(i_label, &s1[2], 1);
267   dfsan_set_label(j_label, &s2[2], 1);
268 
269   rv = strncasecmp(s1, s2, 0);
270   assert(rv == 0); // Compare zero chars.
271   ASSERT_ZERO_LABEL(rv);
272 
273   rv = strncasecmp(s1, s2, 1);
274   assert(rv == 0); // 'A' == 'a'
275   ASSERT_ZERO_LABEL(rv);
276 
277   rv = strncasecmp(s1, s2, 2);
278   assert(rv == 0); // 'b' == 'B'
279   ASSERT_ZERO_LABEL(rv);
280 
281   rv = strncasecmp(s1, s2, 3);
282   assert(rv > 0); // 'Z' > 'y'
283 #ifdef STRICT_DATA_DEPENDENCIES
284   ASSERT_ZERO_LABEL(rv);
285 #else
286   ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
287 #endif
288 }
289 
290 void test_strchr() {
291   char str1[] = "str1";
292   dfsan_set_label(i_label, &str1[3], 1);
293 
294   char *crv = strchr(str1, 'r');
295   assert(crv == &str1[2]);
296   ASSERT_ZERO_LABEL(crv);
297 
298   crv = strchr(str1, '1');
299   assert(crv == &str1[3]);
300 #ifdef STRICT_DATA_DEPENDENCIES
301   ASSERT_ZERO_LABEL(crv);
302 #else
303   ASSERT_LABEL(crv, i_label);
304 #endif
305 
306   crv = strchr(str1, 'x');
307   assert(!crv);
308 #ifdef STRICT_DATA_DEPENDENCIES
309   ASSERT_ZERO_LABEL(crv);
310 #else
311   ASSERT_LABEL(crv, i_label);
312 #endif
313 
314   // `man strchr` says:
315   // The terminating null byte is considered part of the string, so that if c
316   // is specified as '\0', these functions return a pointer to the terminator.
317   crv = strchr(str1, '\0');
318   assert(crv == &str1[4]);
319 #ifdef STRICT_DATA_DEPENDENCIES
320   ASSERT_ZERO_LABEL(crv);
321 #else
322   ASSERT_LABEL(crv, i_label);
323 #endif
324 }
325 
326 void test_calloc() {
327   // With any luck this sequence of calls will cause calloc to return the same
328   // pointer both times.  This is probably the best we can do to test this
329   // function.
330   char *crv = (char *) calloc(4096, 1);
331   ASSERT_ZERO_LABEL(crv[0]);
332   dfsan_set_label(i_label, crv, 100);
333   free(crv);
334 
335   crv = (char *) calloc(4096, 1);
336   ASSERT_ZERO_LABEL(crv[0]);
337   free(crv);
338 }
339 
340 void test_recvmmsg() {
341   int sockfds[2];
342   int ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sockfds);
343   assert(ret != -1);
344 
345   // Setup messages to send.
346   struct mmsghdr smmsg[2] = {};
347   char sbuf0[] = "abcdefghijkl";
348   struct iovec siov0[2] = {{&sbuf0[0], 4}, {&sbuf0[4], 4}};
349   smmsg[0].msg_hdr.msg_iov = siov0;
350   smmsg[0].msg_hdr.msg_iovlen = 2;
351   char sbuf1[] = "1234567890";
352   struct iovec siov1[1] = {{&sbuf1[0], 7}};
353   smmsg[1].msg_hdr.msg_iov = siov1;
354   smmsg[1].msg_hdr.msg_iovlen = 1;
355 
356   // Send messages.
357   int sent_msgs = sendmmsg(sockfds[0], smmsg, 2, 0);
358   assert(sent_msgs == 2);
359 
360   // Setup receive buffers.
361   struct mmsghdr rmmsg[2] = {};
362   char rbuf0[128];
363   struct iovec riov0[2] = {{&rbuf0[0], 4}, {&rbuf0[4], 4}};
364   rmmsg[0].msg_hdr.msg_iov = riov0;
365   rmmsg[0].msg_hdr.msg_iovlen = 2;
366   char rbuf1[128];
367   struct iovec riov1[1] = {{&rbuf1[0], 16}};
368   rmmsg[1].msg_hdr.msg_iov = riov1;
369   rmmsg[1].msg_hdr.msg_iovlen = 1;
370   struct timespec timeout = {1, 1};
371   dfsan_set_label(i_label, rbuf0, sizeof(rbuf0));
372   dfsan_set_label(i_label, rbuf1, sizeof(rbuf1));
373   dfsan_set_label(i_label, &rmmsg[0].msg_len, sizeof(rmmsg[0].msg_len));
374   dfsan_set_label(i_label, &rmmsg[1].msg_len, sizeof(rmmsg[1].msg_len));
375   dfsan_set_label(i_label, &timeout, sizeof(timeout));
376 
377   // Receive messages and check labels.
378   int received_msgs = recvmmsg(sockfds[1], rmmsg, 2, 0, &timeout);
379   assert(received_msgs == sent_msgs);
380   assert(rmmsg[0].msg_len == smmsg[0].msg_len);
381   assert(rmmsg[1].msg_len == smmsg[1].msg_len);
382   assert(memcmp(sbuf0, rbuf0, 8) == 0);
383   assert(memcmp(sbuf1, rbuf1, 7) == 0);
384   ASSERT_ZERO_LABEL(received_msgs);
385   ASSERT_ZERO_LABEL(rmmsg[0].msg_len);
386   ASSERT_ZERO_LABEL(rmmsg[1].msg_len);
387   ASSERT_READ_ZERO_LABEL(&rbuf0[0], 8);
388   ASSERT_READ_LABEL(&rbuf0[8], 1, i_label);
389   ASSERT_READ_ZERO_LABEL(&rbuf1[0], 7);
390   ASSERT_READ_LABEL(&rbuf1[7], 1, i_label);
391   ASSERT_LABEL(timeout.tv_sec, i_label);
392   ASSERT_LABEL(timeout.tv_nsec, i_label);
393 
394   close(sockfds[0]);
395   close(sockfds[1]);
396 }
397 
398 void test_recvmsg() {
399   int sockfds[2];
400   int ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sockfds);
401   assert(ret != -1);
402 
403   char sbuf[] = "abcdefghijkl";
404   struct iovec siovs[2] = {{&sbuf[0], 4}, {&sbuf[4], 4}};
405   struct msghdr smsg = {};
406   smsg.msg_iov = siovs;
407   smsg.msg_iovlen = 2;
408 
409   ssize_t sent = sendmsg(sockfds[0], &smsg, 0);
410   assert(sent > 0);
411 
412   char rbuf[128];
413   struct iovec riovs[2] = {{&rbuf[0], 4}, {&rbuf[4], 4}};
414   struct msghdr rmsg = {};
415   rmsg.msg_iov = riovs;
416   rmsg.msg_iovlen = 2;
417 
418   dfsan_set_label(i_label, rbuf, sizeof(rbuf));
419   dfsan_set_label(i_label, &rmsg, sizeof(rmsg));
420 
421   ssize_t received = recvmsg(sockfds[1], &rmsg, 0);
422   assert(received == sent);
423   assert(memcmp(sbuf, rbuf, 8) == 0);
424   ASSERT_ZERO_LABEL(received);
425   ASSERT_READ_ZERO_LABEL(&rmsg, sizeof(rmsg));
426   ASSERT_READ_ZERO_LABEL(&rbuf[0], 8);
427   ASSERT_READ_LABEL(&rbuf[8], 1, i_label);
428 
429   close(sockfds[0]);
430   close(sockfds[1]);
431 }
432 
433 void test_read() {
434   char buf[16];
435   dfsan_set_label(i_label, buf, 1);
436   dfsan_set_label(j_label, buf + 15, 1);
437 
438   ASSERT_LABEL(buf[0], i_label);
439   ASSERT_LABEL(buf[15], j_label);
440 
441   int fd = open("/dev/zero", O_RDONLY);
442   int rv = read(fd, buf, sizeof(buf));
443   assert(rv == sizeof(buf));
444   ASSERT_ZERO_LABEL(rv);
445   ASSERT_ZERO_LABEL(buf[0]);
446   ASSERT_ZERO_LABEL(buf[15]);
447   close(fd);
448 }
449 
450 void test_pread() {
451   char buf[16];
452   dfsan_set_label(i_label, buf, 1);
453   dfsan_set_label(j_label, buf + 15, 1);
454 
455   ASSERT_LABEL(buf[0], i_label);
456   ASSERT_LABEL(buf[15], j_label);
457 
458   int fd = open("/bin/sh", O_RDONLY);
459   int rv = pread(fd, buf, sizeof(buf), 0);
460   assert(rv == sizeof(buf));
461   ASSERT_ZERO_LABEL(rv);
462   ASSERT_ZERO_LABEL(buf[0]);
463   ASSERT_ZERO_LABEL(buf[15]);
464   close(fd);
465 }
466 
467 void test_dlopen() {
468   void *map = dlopen(NULL, RTLD_NOW);
469   assert(map);
470   ASSERT_ZERO_LABEL(map);
471   dlclose(map);
472   map = dlopen("/nonexistent", RTLD_NOW);
473   assert(!map);
474   ASSERT_ZERO_LABEL(map);
475 }
476 
477 void test_clock_gettime() {
478   struct timespec tp;
479   dfsan_set_label(j_label, ((char *)&tp) + 3, 1);
480   int t = clock_gettime(CLOCK_REALTIME, &tp);
481   assert(t == 0);
482   ASSERT_ZERO_LABEL(t);
483   ASSERT_ZERO_LABEL(((char *)&tp)[3]);
484 }
485 
486 void test_ctime_r() {
487   char *buf = (char*) malloc(64);
488   time_t t = 0;
489 
490   char *ret = ctime_r(&t, buf);
491   ASSERT_ZERO_LABEL(ret);
492   assert(buf == ret);
493   ASSERT_READ_ZERO_LABEL(buf, strlen(buf) + 1);
494 
495   dfsan_set_label(i_label, &t, sizeof(t));
496   ret = ctime_r(&t, buf);
497   ASSERT_ZERO_LABEL(ret);
498   ASSERT_READ_LABEL(buf, strlen(buf) + 1, i_label);
499 
500   t = 0;
501   dfsan_set_label(j_label, &buf, sizeof(&buf));
502   ret = ctime_r(&t, buf);
503   ASSERT_LABEL(ret, j_label);
504   ASSERT_READ_ZERO_LABEL(buf, strlen(buf) + 1);
505 }
506 
507 static int write_callback_count = 0;
508 static int last_fd;
509 static const unsigned char *last_buf;
510 static size_t last_count;
511 
512 void write_callback(int fd, const void *buf, size_t count) {
513   write_callback_count++;
514 
515   last_fd = fd;
516   last_buf = (const unsigned char*) buf;
517   last_count = count;
518 }
519 
520 void test_dfsan_set_write_callback() {
521   char buf[] = "Sample chars";
522   int buf_len = strlen(buf);
523 
524   int fd = open("/dev/null", O_WRONLY);
525 
526   dfsan_set_write_callback(write_callback);
527 
528   write_callback_count = 0;
529 
530   // Callback should be invoked on every call to write().
531   int res = write(fd, buf, buf_len);
532   assert(write_callback_count == 1);
533   ASSERT_READ_ZERO_LABEL(&res, sizeof(res));
534   ASSERT_READ_ZERO_LABEL(&last_fd, sizeof(last_fd));
535   ASSERT_READ_ZERO_LABEL(last_buf, sizeof(last_buf));
536   ASSERT_READ_ZERO_LABEL(&last_count, sizeof(last_count));
537 
538   // Add a label to write() arguments.  Check that the labels are readable from
539   // the values passed to the callback.
540   dfsan_set_label(i_label, &fd, sizeof(fd));
541   dfsan_set_label(j_label, &(buf[3]), 1);
542   dfsan_set_label(k_label, &buf_len, sizeof(buf_len));
543 
544   res = write(fd, buf, buf_len);
545   assert(write_callback_count == 2);
546   ASSERT_READ_ZERO_LABEL(&res, sizeof(res));
547   ASSERT_READ_LABEL(&last_fd, sizeof(last_fd), i_label);
548   ASSERT_READ_LABEL(&last_buf[3], sizeof(last_buf[3]), j_label);
549   ASSERT_READ_LABEL(last_buf, sizeof(last_buf), j_label);
550   ASSERT_READ_LABEL(&last_count, sizeof(last_count), k_label);
551 
552   dfsan_set_write_callback(NULL);
553 }
554 
555 void test_fgets() {
556   char *buf = (char*) malloc(128);
557   FILE *f = fopen("/etc/passwd", "r");
558   dfsan_set_label(j_label, buf, 1);
559   char *ret = fgets(buf, sizeof(buf), f);
560   assert(ret == buf);
561   ASSERT_ZERO_LABEL(ret);
562   ASSERT_READ_ZERO_LABEL(buf, 128);
563   dfsan_set_label(j_label, &buf, sizeof(&buf));
564   ret = fgets(buf, sizeof(buf), f);
565   ASSERT_LABEL(ret, j_label);
566   fclose(f);
567 }
568 
569 void test_getcwd() {
570   char buf[1024];
571   char *ptr = buf;
572   dfsan_set_label(i_label, buf + 2, 2);
573   char* ret = getcwd(buf, sizeof(buf));
574   assert(ret == buf);
575   assert(ret[0] == '/');
576   ASSERT_READ_ZERO_LABEL(buf + 2, 2);
577   dfsan_set_label(i_label, &ptr, sizeof(ptr));
578   ret = getcwd(ptr, sizeof(buf));
579   ASSERT_LABEL(ret, i_label);
580 }
581 
582 void test_get_current_dir_name() {
583   char* ret = get_current_dir_name();
584   assert(ret);
585   assert(ret[0] == '/');
586   ASSERT_READ_ZERO_LABEL(ret, strlen(ret) + 1);
587 }
588 
589 void test_gethostname() {
590   char buf[1024];
591   dfsan_set_label(i_label, buf + 2, 2);
592   assert(gethostname(buf, sizeof(buf)) == 0);
593   ASSERT_READ_ZERO_LABEL(buf + 2, 2);
594 }
595 
596 void test_getrlimit() {
597   struct rlimit rlim;
598   dfsan_set_label(i_label, &rlim, sizeof(rlim));
599   assert(getrlimit(RLIMIT_CPU, &rlim) == 0);
600   ASSERT_READ_ZERO_LABEL(&rlim, sizeof(rlim));
601 }
602 
603 void test_getrusage() {
604   struct rusage usage;
605   dfsan_set_label(i_label, &usage, sizeof(usage));
606   assert(getrusage(RUSAGE_SELF, &usage) == 0);
607   ASSERT_READ_ZERO_LABEL(&usage, sizeof(usage));
608 }
609 
610 void test_strcpy() {
611   char src[] = "hello world";
612   char dst[sizeof(src) + 2];
613   dfsan_set_label(0, src, sizeof(src));
614   dfsan_set_label(0, dst, sizeof(dst));
615   dfsan_set_label(i_label, src + 2, 1);
616   dfsan_set_label(j_label, src + 3, 1);
617   dfsan_set_label(j_label, dst + 4, 1);
618   dfsan_set_label(i_label, dst + 12, 1);
619   char *ret = strcpy(dst, src);
620   assert(ret == dst);
621   assert(strcmp(src, dst) == 0);
622   for (int i = 0; i < strlen(src) + 1; ++i) {
623     assert(dfsan_get_label(dst[i]) == dfsan_get_label(src[i]));
624   }
625   // Note: if strlen(src) + 1 were used instead to compute the first untouched
626   // byte of dest, the label would be I|J. This is because strlen() might
627   // return a non-zero label, and because by default pointer labels are not
628   // ignored on loads.
629   ASSERT_LABEL(dst[12], i_label);
630 }
631 
632 void test_strtol() {
633   char buf[] = "1234578910";
634   char *endptr = NULL;
635   dfsan_set_label(i_label, buf + 1, 1);
636   dfsan_set_label(j_label, buf + 10, 1);
637   long int ret = strtol(buf, &endptr, 10);
638   assert(ret == 1234578910);
639   assert(endptr == buf + 10);
640   ASSERT_LABEL(ret, i_j_label);
641 }
642 
643 void test_strtoll() {
644   char buf[] = "1234578910 ";
645   char *endptr = NULL;
646   dfsan_set_label(i_label, buf + 1, 1);
647   dfsan_set_label(j_label, buf + 2, 1);
648   long long int ret = strtoll(buf, &endptr, 10);
649   assert(ret == 1234578910);
650   assert(endptr == buf + 10);
651   ASSERT_LABEL(ret, i_j_label);
652 }
653 
654 void test_strtoul() {
655   char buf[] = "ffffffffffffaa";
656   char *endptr = NULL;
657   dfsan_set_label(i_label, buf + 1, 1);
658   dfsan_set_label(j_label, buf + 2, 1);
659   long unsigned int ret = strtol(buf, &endptr, 16);
660   assert(ret == 72057594037927850);
661   assert(endptr == buf + 14);
662   ASSERT_LABEL(ret, i_j_label);
663 }
664 
665 void test_strtoull() {
666   char buf[] = "ffffffffffffffaa";
667   char *endptr = NULL;
668   dfsan_set_label(i_label, buf + 1, 1);
669   dfsan_set_label(j_label, buf + 2, 1);
670   long long unsigned int ret = strtoull(buf, &endptr, 16);
671   assert(ret == 0xffffffffffffffaa);
672   assert(endptr == buf + 16);
673   ASSERT_LABEL(ret, i_j_label);
674 }
675 
676 void test_strtod() {
677   char buf[] = "12345.76 foo";
678   char *endptr = NULL;
679   dfsan_set_label(i_label, buf + 1, 1);
680   dfsan_set_label(j_label, buf + 6, 1);
681   double ret = strtod(buf, &endptr);
682   assert(ret == 12345.76);
683   assert(endptr == buf + 8);
684   ASSERT_LABEL(ret, i_j_label);
685 }
686 
687 void test_time() {
688   time_t t = 0;
689   dfsan_set_label(i_label, &t, 1);
690   time_t ret = time(&t);
691   assert(ret == t);
692   assert(ret > 0);
693   ASSERT_ZERO_LABEL(t);
694 }
695 
696 void test_inet_pton() {
697   char addr4[] = "127.0.0.1";
698   dfsan_set_label(i_label, addr4 + 3, 1);
699   struct in_addr in4;
700   int ret4 = inet_pton(AF_INET, addr4, &in4);
701   assert(ret4 == 1);
702   ASSERT_READ_LABEL(&in4, sizeof(in4), i_label);
703   assert(in4.s_addr == htonl(0x7f000001));
704 
705   char addr6[] = "::1";
706   dfsan_set_label(j_label, addr6 + 3, 1);
707   struct in6_addr in6;
708   int ret6 = inet_pton(AF_INET6, addr6, &in6);
709   assert(ret6 == 1);
710   ASSERT_READ_LABEL(((char *) &in6) + sizeof(in6) - 1, 1, j_label);
711 }
712 
713 void test_localtime_r() {
714   time_t t0 = 1384800998;
715   struct tm t1;
716   dfsan_set_label(i_label, &t0, sizeof(t0));
717   struct tm* ret = localtime_r(&t0, &t1);
718   assert(ret == &t1);
719   assert(t1.tm_min == 56);
720   ASSERT_LABEL(t1.tm_mon, i_label);
721 }
722 
723 void test_getpwuid_r() {
724   struct passwd pwd;
725   char buf[1024];
726   struct passwd *result;
727 
728   dfsan_set_label(i_label, &pwd, 4);
729   int ret = getpwuid_r(0, &pwd, buf, sizeof(buf), &result);
730   assert(ret == 0);
731   assert(strcmp(pwd.pw_name, "root") == 0);
732   assert(result == &pwd);
733   ASSERT_READ_ZERO_LABEL(&pwd, 4);
734 }
735 
736 void test_epoll_wait() {
737   // Set up a pipe to monitor with epoll.
738   int pipe_fds[2];
739   int ret = pipe(pipe_fds);
740   assert(ret != -1);
741 
742   // Configure epoll to monitor the pipe.
743   int epfd = epoll_create1(0);
744   assert(epfd != -1);
745   struct epoll_event event;
746   event.events = EPOLLIN;
747   event.data.fd = pipe_fds[0];
748   ret = epoll_ctl(epfd, EPOLL_CTL_ADD, pipe_fds[0], &event);
749   assert(ret != -1);
750 
751   // Test epoll_wait when no events have occurred.
752   event = {};
753   dfsan_set_label(i_label, &event, sizeof(event));
754   ret = epoll_wait(epfd, &event, /*maxevents=*/1, /*timeout=*/0);
755   assert(ret == 0);
756   assert(event.events == 0);
757   assert(event.data.fd == 0);
758   ASSERT_ZERO_LABEL(ret);
759   ASSERT_READ_LABEL(&event, sizeof(event), i_label);
760 
761   // Test epoll_wait when an event occurs.
762   write(pipe_fds[1], "x", 1);
763   ret = epoll_wait(epfd, &event, /*maxevents=*/1, /*timeout=*/0);
764   assert(ret == 1);
765   assert(event.events == EPOLLIN);
766   assert(event.data.fd == pipe_fds[0]);
767   ASSERT_ZERO_LABEL(ret);
768   ASSERT_READ_ZERO_LABEL(&event, sizeof(event));
769 
770   // Clean up.
771   close(epfd);
772   close(pipe_fds[0]);
773   close(pipe_fds[1]);
774 }
775 
776 void test_poll() {
777   struct pollfd fd;
778   fd.fd = 0;
779   fd.events = POLLIN;
780   dfsan_set_label(i_label, &fd.revents, sizeof(fd.revents));
781   int ret = poll(&fd, 1, 1);
782   ASSERT_ZERO_LABEL(fd.revents);
783   assert(ret >= 0);
784 }
785 
786 void test_select() {
787   struct timeval t;
788   fd_set fds;
789   t.tv_sec = 2;
790   FD_SET(0, &fds);
791   dfsan_set_label(i_label, &fds, sizeof(fds));
792   dfsan_set_label(j_label, &t, sizeof(t));
793   int ret = select(1, &fds, NULL, NULL, &t);
794   assert(ret >= 0);
795   ASSERT_ZERO_LABEL(t.tv_sec);
796   ASSERT_READ_ZERO_LABEL(&fds, sizeof(fds));
797 }
798 
799 void test_sched_getaffinity() {
800   cpu_set_t mask;
801   dfsan_set_label(j_label, &mask, 1);
802   int ret = sched_getaffinity(0, sizeof(mask), &mask);
803   assert(ret == 0);
804   ASSERT_READ_ZERO_LABEL(&mask, sizeof(mask));
805 }
806 
807 void test_sigemptyset() {
808   sigset_t set;
809   dfsan_set_label(j_label, &set, 1);
810   int ret = sigemptyset(&set);
811   assert(ret == 0);
812   ASSERT_READ_ZERO_LABEL(&set, sizeof(set));
813 }
814 
815 void test_sigaction() {
816   struct sigaction oldact;
817   dfsan_set_label(j_label, &oldact, 1);
818   int ret = sigaction(SIGUSR1, NULL, &oldact);
819   assert(ret == 0);
820   ASSERT_READ_ZERO_LABEL(&oldact, sizeof(oldact));
821 }
822 
823 void test_sigaltstack() {
824   stack_t old_altstack = {};
825   dfsan_set_label(j_label, &old_altstack, sizeof(old_altstack));
826   int ret = sigaltstack(NULL, &old_altstack);
827   assert(ret == 0);
828   ASSERT_ZERO_LABEL(ret);
829   ASSERT_READ_ZERO_LABEL(&old_altstack, sizeof(old_altstack));
830 }
831 
832 void test_gettimeofday() {
833   struct timeval tv;
834   struct timezone tz;
835   dfsan_set_label(i_label, &tv, sizeof(tv));
836   dfsan_set_label(j_label, &tz, sizeof(tz));
837   int ret = gettimeofday(&tv, &tz);
838   assert(ret == 0);
839   ASSERT_READ_ZERO_LABEL(&tv, sizeof(tv));
840   ASSERT_READ_ZERO_LABEL(&tz, sizeof(tz));
841 }
842 
843 void *pthread_create_test_cb(void *p) {
844   assert(p == (void *)1);
845   ASSERT_ZERO_LABEL(p);
846   return (void *)2;
847 }
848 
849 void test_pthread_create() {
850   pthread_t pt;
851   pthread_create(&pt, 0, pthread_create_test_cb, (void *)1);
852   void *cbrv;
853   dfsan_set_label(i_label, &cbrv, sizeof(cbrv));
854   int ret = pthread_join(pt, &cbrv);
855   assert(ret == 0);
856   assert(cbrv == (void *)2);
857   ASSERT_ZERO_LABEL(ret);
858   ASSERT_ZERO_LABEL(cbrv);
859 }
860 
861 // Tested by test_pthread_create().  This empty function is here to appease the
862 // check-wrappers script.
863 void test_pthread_join() {}
864 
865 int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
866                             void *data) {
867   assert(data == (void *)3);
868   ASSERT_ZERO_LABEL(info);
869   ASSERT_ZERO_LABEL(size);
870   ASSERT_ZERO_LABEL(data);
871   return 0;
872 }
873 
874 void test_dl_iterate_phdr() {
875   dl_iterate_phdr(dl_iterate_phdr_test_cb, (void *)3);
876 }
877 
878 // On glibc < 2.27, this symbol is not available.  Mark it weak so we can skip
879 // testing in this case.
880 __attribute__((weak)) extern "C" void _dl_get_tls_static_info(size_t *sizep,
881                                                               size_t *alignp);
882 
883 void test__dl_get_tls_static_info() {
884   if (!_dl_get_tls_static_info)
885     return;
886   size_t sizep = 0, alignp = 0;
887   dfsan_set_label(i_label, &sizep, sizeof(sizep));
888   dfsan_set_label(i_label, &alignp, sizeof(alignp));
889   _dl_get_tls_static_info(&sizep, &alignp);
890   ASSERT_ZERO_LABEL(sizep);
891   ASSERT_ZERO_LABEL(alignp);
892 }
893 
894 void test_strrchr() {
895   char str1[] = "str1str1";
896   dfsan_set_label(i_label, &str1[7], 1);
897 
898   char *rv = strrchr(str1, 'r');
899   assert(rv == &str1[6]);
900 #ifdef STRICT_DATA_DEPENDENCIES
901   ASSERT_ZERO_LABEL(rv);
902 #else
903   ASSERT_LABEL(rv, i_label);
904 #endif
905 }
906 
907 void test_strstr() {
908   char str1[] = "str1str1";
909   dfsan_set_label(i_label, &str1[3], 1);
910   dfsan_set_label(j_label, &str1[5], 1);
911 
912   char *rv = strstr(str1, "1s");
913   assert(rv == &str1[3]);
914 #ifdef STRICT_DATA_DEPENDENCIES
915   ASSERT_ZERO_LABEL(rv);
916 #else
917   ASSERT_LABEL(rv, i_label);
918 #endif
919 
920   rv = strstr(str1, "2s");
921   assert(rv == NULL);
922 #ifdef STRICT_DATA_DEPENDENCIES
923   ASSERT_ZERO_LABEL(rv);
924 #else
925   ASSERT_LABEL(rv, i_j_label);
926 #endif
927 }
928 
929 void test_strpbrk() {
930   char s[] = "abcdefg";
931   char accept[] = "123fd";
932   dfsan_set_label(i_label, &s[5], 1);
933   dfsan_set_label(j_label, &accept[1], 1);
934 
935   char *rv = strpbrk(s, accept);
936   assert(rv == &s[3]);
937 #ifdef STRICT_DATA_DEPENDENCIES
938   ASSERT_ZERO_LABEL(rv);
939 #else
940   ASSERT_LABEL(rv, j_label);
941 #endif
942 
943   char *ps = s;
944   dfsan_set_label(j_label, &ps, sizeof(ps));
945 
946   rv = strpbrk(ps, "123gf");
947   assert(rv == &s[5]);
948 #ifdef STRICT_DATA_DEPENDENCIES
949   ASSERT_LABEL(rv, j_label);
950 #else
951   ASSERT_LABEL(rv, i_j_label);
952 #endif
953 
954   rv = strpbrk(ps, "123");
955   assert(rv == NULL);
956 #ifdef STRICT_DATA_DEPENDENCIES
957   ASSERT_ZERO_LABEL(rv);
958 #else
959   ASSERT_LABEL(rv, i_j_label);
960 #endif
961 }
962 
963 void test_memchr() {
964   char str1[] = "str1";
965   dfsan_set_label(i_label, &str1[3], 1);
966   dfsan_set_label(j_label, &str1[4], 1);
967 
968   char *crv = (char *) memchr(str1, 'r', sizeof(str1));
969   assert(crv == &str1[2]);
970   ASSERT_ZERO_LABEL(crv);
971 
972   crv = (char *) memchr(str1, '1', sizeof(str1));
973   assert(crv == &str1[3]);
974 #ifdef STRICT_DATA_DEPENDENCIES
975   ASSERT_ZERO_LABEL(crv);
976 #else
977   ASSERT_LABEL(crv, i_label);
978 #endif
979 
980   crv = (char *) memchr(str1, 'x', sizeof(str1));
981   assert(!crv);
982 #ifdef STRICT_DATA_DEPENDENCIES
983   ASSERT_ZERO_LABEL(crv);
984 #else
985   ASSERT_LABEL(crv, i_j_label);
986 #endif
987 }
988 
989 void alarm_handler(int unused) {
990   ;
991 }
992 
993 void test_nanosleep() {
994   struct timespec req, rem;
995   req.tv_sec = 1;
996   req.tv_nsec = 0;
997   dfsan_set_label(i_label, &rem, sizeof(rem));
998 
999   // non interrupted
1000   int rv = nanosleep(&req, &rem);
1001   assert(rv == 0);
1002   ASSERT_ZERO_LABEL(rv);
1003   ASSERT_READ_LABEL(&rem, 1, i_label);
1004 
1005   // interrupted by an alarm
1006   signal(SIGALRM, alarm_handler);
1007   req.tv_sec = 3;
1008   alarm(1);
1009   rv = nanosleep(&req, &rem);
1010   assert(rv == -1);
1011   ASSERT_ZERO_LABEL(rv);
1012   ASSERT_READ_ZERO_LABEL(&rem, sizeof(rem));
1013 }
1014 
1015 void test_socketpair() {
1016   int fd[2];
1017 
1018   dfsan_set_label(i_label, fd, sizeof(fd));
1019   int rv = socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
1020   assert(rv == 0);
1021   ASSERT_ZERO_LABEL(rv);
1022   ASSERT_READ_ZERO_LABEL(fd, sizeof(fd));
1023 }
1024 
1025 void test_getpeername() {
1026   int sockfds[2];
1027   int ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sockfds);
1028   assert(ret != -1);
1029 
1030   struct sockaddr addr = {};
1031   socklen_t addrlen = sizeof(addr);
1032   dfsan_set_label(i_label, &addr, addrlen);
1033   dfsan_set_label(i_label, &addrlen, sizeof(addrlen));
1034 
1035   ret = getpeername(sockfds[0], &addr, &addrlen);
1036   assert(ret != -1);
1037   ASSERT_ZERO_LABEL(ret);
1038   ASSERT_ZERO_LABEL(addrlen);
1039   assert(addrlen < sizeof(addr));
1040   ASSERT_READ_ZERO_LABEL(&addr, addrlen);
1041   ASSERT_READ_LABEL(((char *)&addr) + addrlen, 1, i_label);
1042 
1043   close(sockfds[0]);
1044   close(sockfds[1]);
1045 }
1046 
1047 void test_getsockname() {
1048   int sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
1049   assert(sockfd != -1);
1050 
1051   struct sockaddr addr = {};
1052   socklen_t addrlen = sizeof(addr);
1053   dfsan_set_label(i_label, &addr, addrlen);
1054   dfsan_set_label(i_label, &addrlen, sizeof(addrlen));
1055 
1056   int ret = getsockname(sockfd, &addr, &addrlen);
1057   assert(ret != -1);
1058   ASSERT_ZERO_LABEL(ret);
1059   ASSERT_ZERO_LABEL(addrlen);
1060   assert(addrlen < sizeof(addr));
1061   ASSERT_READ_ZERO_LABEL(&addr, addrlen);
1062   ASSERT_READ_LABEL(((char *)&addr) + addrlen, 1, i_label);
1063 
1064   close(sockfd);
1065 }
1066 
1067 void test_getsockopt() {
1068   int sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
1069   assert(sockfd != -1);
1070 
1071   int optval[2] = {-1, -1};
1072   socklen_t optlen = sizeof(optval);
1073   dfsan_set_label(i_label, &optval, sizeof(optval));
1074   dfsan_set_label(i_label, &optlen, sizeof(optlen));
1075   int ret = getsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen);
1076   assert(ret != -1);
1077   assert(optlen == sizeof(int));
1078   assert(optval[0] == 0);
1079   assert(optval[1] == -1);
1080   ASSERT_ZERO_LABEL(ret);
1081   ASSERT_ZERO_LABEL(optlen);
1082   ASSERT_ZERO_LABEL(optval[0]);
1083   ASSERT_LABEL(optval[1], i_label);
1084 
1085   close(sockfd);
1086 }
1087 
1088 void test_write() {
1089   int fd = open("/dev/null", O_WRONLY);
1090 
1091   char buf[] = "a string";
1092   int len = strlen(buf);
1093 
1094   // The result of a write always unlabeled.
1095   int res = write(fd, buf, len);
1096   assert(res > 0);
1097   ASSERT_ZERO_LABEL(res);
1098 
1099   // Label all arguments to write().
1100   dfsan_set_label(i_label, &(buf[3]), 1);
1101   dfsan_set_label(j_label, &fd, sizeof(fd));
1102   dfsan_set_label(i_label, &len, sizeof(len));
1103 
1104   // The value returned by write() should have no label.
1105   res = write(fd, buf, len);
1106   ASSERT_ZERO_LABEL(res);
1107 
1108   close(fd);
1109 }
1110 
1111 template <class T>
1112 void test_sprintf_chunk(const char* expected, const char* format, T arg) {
1113   char buf[512];
1114   memset(buf, 'a', sizeof(buf));
1115 
1116   char padded_expected[512];
1117   strcpy(padded_expected, "foo ");
1118   strcat(padded_expected, expected);
1119   strcat(padded_expected, " bar");
1120 
1121   char padded_format[512];
1122   strcpy(padded_format, "foo ");
1123   strcat(padded_format, format);
1124   strcat(padded_format, " bar");
1125 
1126   // Non labelled arg.
1127   assert(sprintf(buf, padded_format,  arg) == strlen(padded_expected));
1128   assert(strcmp(buf, padded_expected) == 0);
1129   ASSERT_READ_LABEL(buf, strlen(padded_expected), 0);
1130   memset(buf, 'a', sizeof(buf));
1131 
1132   // Labelled arg.
1133   dfsan_set_label(i_label, &arg, sizeof(arg));
1134   assert(sprintf(buf, padded_format,  arg) == strlen(padded_expected));
1135   assert(strcmp(buf, padded_expected) == 0);
1136   ASSERT_READ_LABEL(buf, 4, 0);
1137   ASSERT_READ_LABEL(buf + 4, strlen(padded_expected) - 8, i_label);
1138   ASSERT_READ_LABEL(buf + (strlen(padded_expected) - 4), 4, 0);
1139 }
1140 
1141 void test_sprintf() {
1142   char buf[2048];
1143   memset(buf, 'a', sizeof(buf));
1144 
1145   // Test formatting (no conversion specifier).
1146   assert(sprintf(buf, "Hello world!") == 12);
1147   assert(strcmp(buf, "Hello world!") == 0);
1148   ASSERT_READ_LABEL(buf, sizeof(buf), 0);
1149 
1150   // Test for extra arguments.
1151   assert(sprintf(buf, "Hello world!", 42, "hello") == 12);
1152   assert(strcmp(buf, "Hello world!") == 0);
1153   ASSERT_READ_LABEL(buf, sizeof(buf), 0);
1154 
1155   // Test formatting & label propagation (multiple conversion specifiers): %s,
1156   // %d, %n, %f, and %%.
1157   const char* s = "world";
1158   int m = 8;
1159   int d = 27;
1160   dfsan_set_label(k_label, (void *) (s + 1), 2);
1161   dfsan_set_label(i_label, &m, sizeof(m));
1162   dfsan_set_label(j_label, &d, sizeof(d));
1163   int n;
1164   int r = sprintf(buf, "hello %s, %-d/%d/%d %f %% %n%d", s, 2014, m, d,
1165                   12345.6781234, &n, 1000);
1166   assert(r == 42);
1167   assert(strcmp(buf, "hello world, 2014/8/27 12345.678123 % 1000") == 0);
1168   ASSERT_READ_LABEL(buf, 7, 0);
1169   ASSERT_READ_LABEL(buf + 7, 2, k_label);
1170   ASSERT_READ_LABEL(buf + 9, 9, 0);
1171   ASSERT_READ_LABEL(buf + 18, 1, i_label);
1172   ASSERT_READ_LABEL(buf + 19, 1, 0);
1173   ASSERT_READ_LABEL(buf + 20, 2, j_label);
1174   ASSERT_READ_LABEL(buf + 22, 15, 0);
1175   ASSERT_LABEL(r, 0);
1176   assert(n == 38);
1177 
1178   // Test formatting & label propagation (single conversion specifier, with
1179   // additional length and precision modifiers).
1180   test_sprintf_chunk("-559038737", "%d", 0xdeadbeef);
1181   test_sprintf_chunk("3735928559", "%u", 0xdeadbeef);
1182   test_sprintf_chunk("12345", "%i", 12345);
1183   test_sprintf_chunk("751", "%o", 0751);
1184   test_sprintf_chunk("babe", "%x", 0xbabe);
1185   test_sprintf_chunk("0000BABE", "%.8X", 0xbabe);
1186   test_sprintf_chunk("-17", "%hhd", 0xdeadbeef);
1187   test_sprintf_chunk("-16657", "%hd", 0xdeadbeef);
1188   test_sprintf_chunk("deadbeefdeadbeef", "%lx", 0xdeadbeefdeadbeef);
1189   test_sprintf_chunk("0xdeadbeefdeadbeef", "%p",
1190                  (void *)  0xdeadbeefdeadbeef);
1191   test_sprintf_chunk("18446744073709551615", "%ju", (intmax_t) -1);
1192   test_sprintf_chunk("18446744073709551615", "%zu", (size_t) -1);
1193   test_sprintf_chunk("18446744073709551615", "%tu", (size_t) -1);
1194 
1195   test_sprintf_chunk("0x1.f9acffa7eb6bfp-4", "%a", 0.123456);
1196   test_sprintf_chunk("0X1.F9ACFFA7EB6BFP-4", "%A", 0.123456);
1197   test_sprintf_chunk("0.12346", "%.5f", 0.123456);
1198   test_sprintf_chunk("0.123456", "%g", 0.123456);
1199   test_sprintf_chunk("1.234560e-01", "%e", 0.123456);
1200   test_sprintf_chunk("1.234560E-01", "%E", 0.123456);
1201   test_sprintf_chunk("0.1234567891234560", "%.16Lf",
1202                      (long double) 0.123456789123456);
1203 
1204   test_sprintf_chunk("z", "%c", 'z');
1205 
1206   // %n, %s, %d, %f, and %% already tested
1207 
1208   // Test formatting with width passed as an argument.
1209   r = sprintf(buf, "hi %*d my %*s friend %.*f", 3, 1, 6, "dear", 4, 3.14159265359);
1210   assert(r == 30);
1211   assert(strcmp(buf, "hi   1 my   dear friend 3.1416") == 0);
1212 }
1213 
1214 void test_snprintf() {
1215   char buf[2048];
1216   memset(buf, 'a', sizeof(buf));
1217   dfsan_set_label(0, buf, sizeof(buf));
1218   const char* s = "world";
1219   int y = 2014;
1220   int m = 8;
1221   int d = 27;
1222   dfsan_set_label(k_label, (void *) (s + 1), 2);
1223   dfsan_set_label(i_label, &y, sizeof(y));
1224   dfsan_set_label(j_label, &m, sizeof(m));
1225   int r = snprintf(buf, 19, "hello %s, %-d/%d/%d %f", s, y, m, d,
1226                    12345.6781234);
1227   // The return value is the number of bytes that would have been written to
1228   // the final string if enough space had been available.
1229   assert(r == 35);
1230   assert(memcmp(buf, "hello world, 2014/", 19) == 0);
1231   ASSERT_READ_LABEL(buf, 7, 0);
1232   ASSERT_READ_LABEL(buf + 7, 2, k_label);
1233   ASSERT_READ_LABEL(buf + 9, 4, 0);
1234   ASSERT_READ_LABEL(buf + 13, 4, i_label);
1235   ASSERT_READ_LABEL(buf + 17, 2, 0);
1236   ASSERT_LABEL(r, 0);
1237 }
1238 
1239 int main(void) {
1240 #ifdef FAST_16_LABELS
1241   i_label = 1;
1242   j_label = 2;
1243   k_label = 4;
1244 #else
1245   i_label = dfsan_create_label("i", 0);
1246   j_label = dfsan_create_label("j", 0);
1247   k_label = dfsan_create_label("k", 0);
1248 #endif
1249   i_j_label = dfsan_union(i_label, j_label);
1250   assert(i_j_label != i_label);
1251   assert(i_j_label != j_label);
1252   assert(i_j_label != k_label);
1253 
1254   test__dl_get_tls_static_info();
1255   test_bcmp();
1256   test_calloc();
1257   test_clock_gettime();
1258   test_ctime_r();
1259   test_dfsan_set_write_callback();
1260   test_dl_iterate_phdr();
1261   test_dlopen();
1262   test_epoll_wait();
1263   test_fgets();
1264   test_fstat();
1265   test_get_current_dir_name();
1266   test_getcwd();
1267   test_gethostname();
1268   test_getpeername();
1269   test_getpwuid_r();
1270   test_getrlimit();
1271   test_getrusage();
1272   test_getsockname();
1273   test_getsockopt();
1274   test_gettimeofday();
1275   test_inet_pton();
1276   test_localtime_r();
1277   test_memchr();
1278   test_memcmp();
1279   test_memcpy();
1280   test_memset();
1281   test_nanosleep();
1282   test_poll();
1283   test_pread();
1284   test_pthread_create();
1285   test_pthread_join();
1286   test_read();
1287   test_recvmmsg();
1288   test_recvmsg();
1289   test_sched_getaffinity();
1290   test_select();
1291   test_sigaction();
1292   test_sigaltstack();
1293   test_sigemptyset();
1294   test_snprintf();
1295   test_socketpair();
1296   test_sprintf();
1297   test_stat();
1298   test_strcasecmp();
1299   test_strchr();
1300   test_strcmp();
1301   test_strcpy();
1302   test_strdup();
1303   test_strlen();
1304   test_strncasecmp();
1305   test_strncmp();
1306   test_strncpy();
1307   test_strpbrk();
1308   test_strrchr();
1309   test_strstr();
1310   test_strtod();
1311   test_strtol();
1312   test_strtoll();
1313   test_strtoul();
1314   test_strtoull();
1315   test_time();
1316   test_write();
1317 }
1318