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