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