1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s 2 // RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s 3 // RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s 4 // RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=alpha.security.taint,core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s 5 6 //===----------------------------------------------------------------------=== 7 // Declarations 8 //===----------------------------------------------------------------------=== 9 10 // Some functions are so similar to each other that they follow the same code 11 // path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is 12 // defined, make sure to use the variants instead to make sure they are still 13 // checked by the analyzer. 14 15 // Some functions are implemented as builtins. These should be #defined as 16 // BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined. 17 18 // Functions that have variants and are also available as builtins should be 19 // declared carefully! See memcpy() for an example. 20 21 #ifdef USE_BUILTINS 22 # define BUILTIN(f) __builtin_ ## f 23 #else /* USE_BUILTINS */ 24 # define BUILTIN(f) f 25 #endif /* USE_BUILTINS */ 26 27 #define NULL 0 28 typedef typeof(sizeof(int)) size_t; 29 30 void clang_analyzer_eval(int); 31 32 int scanf(const char *restrict format, ...); 33 34 //===----------------------------------------------------------------------=== 35 // strlen() 36 //===----------------------------------------------------------------------=== 37 38 #define strlen BUILTIN(strlen) 39 size_t strlen(const char *s); 40 41 void strlen_constant0() { 42 clang_analyzer_eval(strlen("123") == 3); // expected-warning{{TRUE}} 43 } 44 45 void strlen_constant1() { 46 const char *a = "123"; 47 clang_analyzer_eval(strlen(a) == 3); // expected-warning{{TRUE}} 48 } 49 50 void strlen_constant2(char x) { 51 char a[] = "123"; 52 clang_analyzer_eval(strlen(a) == 3); // expected-warning{{TRUE}} 53 54 a[0] = x; 55 clang_analyzer_eval(strlen(a) == 3); // expected-warning{{UNKNOWN}} 56 } 57 58 size_t strlen_null() { 59 return strlen(0); // expected-warning{{Null pointer argument in call to string length function}} 60 } 61 62 size_t strlen_fn() { 63 return strlen((char*)&strlen_fn); // expected-warning{{Argument to string length function is the address of the function 'strlen_fn', which is not a null-terminated string}} 64 } 65 66 size_t strlen_nonloc() { 67 label: 68 return strlen((char*)&&label); // expected-warning{{Argument to string length function is the address of the label 'label', which is not a null-terminated string}} 69 } 70 71 void strlen_subregion() { 72 struct two_strings { char a[2], b[2]; }; 73 extern void use_two_strings(struct two_strings *); 74 75 struct two_strings z; 76 use_two_strings(&z); 77 78 size_t a = strlen(z.a); 79 z.b[0] = 5; 80 size_t b = strlen(z.a); 81 if (a == 0) 82 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} 83 84 use_two_strings(&z); 85 86 size_t c = strlen(z.a); 87 if (a == 0) 88 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 89 } 90 91 extern void use_string(char *); 92 void strlen_argument(char *x) { 93 size_t a = strlen(x); 94 size_t b = strlen(x); 95 if (a == 0) 96 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} 97 98 use_string(x); 99 100 size_t c = strlen(x); 101 if (a == 0) 102 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 103 } 104 105 extern char global_str[]; 106 void strlen_global() { 107 size_t a = strlen(global_str); 108 size_t b = strlen(global_str); 109 if (a == 0) { 110 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} 111 // Make sure clang_analyzer_eval does not invalidate globals. 112 clang_analyzer_eval(strlen(global_str) == 0); // expected-warning{{TRUE}} 113 } 114 115 // Call a function with unknown effects, which should invalidate globals. 116 use_string(0); 117 118 size_t c = strlen(global_str); 119 if (a == 0) 120 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 121 } 122 123 void strlen_indirect(char *x) { 124 size_t a = strlen(x); 125 char *p = x; 126 char **p2 = &p; 127 size_t b = strlen(x); 128 if (a == 0) 129 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} 130 131 extern void use_string_ptr(char*const*); 132 use_string_ptr(p2); 133 134 size_t c = strlen(x); 135 if (a == 0) 136 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 137 } 138 139 void strlen_indirect2(char *x) { 140 size_t a = strlen(x); 141 char *p = x; 142 char **p2 = &p; 143 extern void use_string_ptr2(char**); 144 use_string_ptr2(p2); 145 146 size_t c = strlen(x); 147 if (a == 0) 148 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 149 } 150 151 void strlen_liveness(const char *x) { 152 if (strlen(x) < 5) 153 return; 154 clang_analyzer_eval(strlen(x) < 5); // expected-warning{{FALSE}} 155 } 156 157 158 size_t strlenWrapper(const char *str) { 159 return strlen(str); 160 } 161 162 extern void invalidate(char *s); 163 164 void testStrlenCallee() { 165 char str[42]; 166 invalidate(str); 167 size_t lenBefore = strlenWrapper(str); 168 invalidate(str); 169 size_t lenAfter = strlenWrapper(str); 170 clang_analyzer_eval(lenBefore == lenAfter); // expected-warning{{UNKNOWN}} 171 } 172 173 174 //===----------------------------------------------------------------------=== 175 // strnlen() 176 //===----------------------------------------------------------------------=== 177 178 size_t strnlen(const char *s, size_t maxlen); 179 180 void strnlen_constant0() { 181 clang_analyzer_eval(strnlen("123", 10) == 3); // expected-warning{{TRUE}} 182 } 183 184 void strnlen_constant1() { 185 const char *a = "123"; 186 clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{TRUE}} 187 } 188 189 void strnlen_constant2(char x) { 190 char a[] = "123"; 191 clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{TRUE}} 192 a[0] = x; 193 clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{UNKNOWN}} 194 } 195 196 void strnlen_constant4() { 197 clang_analyzer_eval(strnlen("123456", 3) == 3); // expected-warning{{TRUE}} 198 } 199 200 void strnlen_constant5() { 201 const char *a = "123456"; 202 clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{TRUE}} 203 } 204 205 void strnlen_constant6(char x) { 206 char a[] = "123456"; 207 clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{TRUE}} 208 a[0] = x; 209 clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{UNKNOWN}} 210 } 211 212 size_t strnlen_null() { 213 return strnlen(0, 3); // expected-warning{{Null pointer argument in call to string length function}} 214 } 215 216 size_t strnlen_fn() { 217 return strnlen((char*)&strlen_fn, 3); // expected-warning{{Argument to string length function is the address of the function 'strlen_fn', which is not a null-terminated string}} 218 } 219 220 size_t strnlen_nonloc() { 221 label: 222 return strnlen((char*)&&label, 3); // expected-warning{{Argument to string length function is the address of the label 'label', which is not a null-terminated string}} 223 } 224 225 void strnlen_zero() { 226 clang_analyzer_eval(strnlen("abc", 0) == 0); // expected-warning{{TRUE}} 227 clang_analyzer_eval(strnlen(NULL, 0) == 0); // expected-warning{{TRUE}} 228 } 229 230 size_t strnlen_compound_literal() { 231 // This used to crash because we don't model the string lengths of 232 // compound literals. 233 return strnlen((char[]) { 'a', 'b', 0 }, 1); 234 } 235 236 size_t strnlen_unknown_limit(float f) { 237 // This used to crash because we don't model the integer values of floats. 238 return strnlen("abc", (int)f); 239 } 240 241 void strnlen_is_not_strlen(char *x) { 242 clang_analyzer_eval(strnlen(x, 10) == strlen(x)); // expected-warning{{UNKNOWN}} 243 } 244 245 void strnlen_at_limit(char *x) { 246 size_t len = strnlen(x, 10); 247 clang_analyzer_eval(len <= 10); // expected-warning{{TRUE}} 248 clang_analyzer_eval(len == 10); // expected-warning{{UNKNOWN}} 249 clang_analyzer_eval(len < 10); // expected-warning{{UNKNOWN}} 250 } 251 252 void strnlen_at_actual(size_t limit) { 253 size_t len = strnlen("abc", limit); 254 clang_analyzer_eval(len <= 3); // expected-warning{{TRUE}} 255 // This is due to eager assertion in strnlen. 256 if (limit == 0) { 257 clang_analyzer_eval(len == 0); // expected-warning{{TRUE}} 258 } else { 259 clang_analyzer_eval(len == 3); // expected-warning{{UNKNOWN}} 260 clang_analyzer_eval(len < 3); // expected-warning{{UNKNOWN}} 261 } 262 } 263 264 //===----------------------------------------------------------------------=== 265 // strcpy() 266 //===----------------------------------------------------------------------=== 267 268 #ifdef VARIANT 269 270 #define __strcpy_chk BUILTIN(__strcpy_chk) 271 char *__strcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen); 272 273 #define strcpy(a,b) __strcpy_chk(a,b,(size_t)-1) 274 275 #else /* VARIANT */ 276 277 #define strcpy BUILTIN(strcpy) 278 char *strcpy(char *restrict s1, const char *restrict s2); 279 280 #endif /* VARIANT */ 281 282 283 void strcpy_null_dst(char *x) { 284 strcpy(NULL, x); // expected-warning{{Null pointer argument in call to string copy function}} 285 } 286 287 void strcpy_null_src(char *x) { 288 strcpy(x, NULL); // expected-warning{{Null pointer argument in call to string copy function}} 289 } 290 291 void strcpy_fn(char *x) { 292 strcpy(x, (char*)&strcpy_fn); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}} 293 } 294 295 void strcpy_fn_const(char *x) { 296 strcpy(x, (const char*)&strcpy_fn); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}} 297 } 298 299 extern int globalInt; 300 void strcpy_effects(char *x, char *y) { 301 char a = x[0]; 302 if (globalInt != 42) 303 return; 304 305 clang_analyzer_eval(strcpy(x, y) == x); // expected-warning{{TRUE}} 306 clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}} 307 clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}} 308 clang_analyzer_eval(globalInt == 42); // expected-warning{{TRUE}} 309 } 310 311 void strcpy_overflow(char *y) { 312 char x[4]; 313 if (strlen(y) == 4) 314 strcpy(x, y); // expected-warning{{String copy function overflows destination buffer}} 315 } 316 317 void strcpy_no_overflow(char *y) { 318 char x[4]; 319 if (strlen(y) == 3) 320 strcpy(x, y); // no-warning 321 } 322 323 //===----------------------------------------------------------------------=== 324 // stpcpy() 325 //===----------------------------------------------------------------------=== 326 327 #ifdef VARIANT 328 329 #define __stpcpy_chk BUILTIN(__stpcpy_chk) 330 char *__stpcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen); 331 332 #define stpcpy(a,b) __stpcpy_chk(a,b,(size_t)-1) 333 334 #else /* VARIANT */ 335 336 #define stpcpy BUILTIN(stpcpy) 337 char *stpcpy(char *restrict s1, const char *restrict s2); 338 339 #endif /* VARIANT */ 340 341 342 void stpcpy_effect(char *x, char *y) { 343 char a = x[0]; 344 345 clang_analyzer_eval(stpcpy(x, y) == &x[strlen(y)]); // expected-warning{{TRUE}} 346 clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}} 347 clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}} 348 } 349 350 void stpcpy_overflow(char *y) { 351 char x[4]; 352 if (strlen(y) == 4) 353 stpcpy(x, y); // expected-warning{{String copy function overflows destination buffer}} 354 } 355 356 void stpcpy_no_overflow(char *y) { 357 char x[4]; 358 if (strlen(y) == 3) 359 stpcpy(x, y); // no-warning 360 } 361 362 //===----------------------------------------------------------------------=== 363 // strcat() 364 //===----------------------------------------------------------------------=== 365 366 #ifdef VARIANT 367 368 #define __strcat_chk BUILTIN(__strcat_chk) 369 char *__strcat_chk(char *restrict s1, const char *restrict s2, size_t destlen); 370 371 #define strcat(a,b) __strcat_chk(a,b,(size_t)-1) 372 373 #else /* VARIANT */ 374 375 #define strcat BUILTIN(strcat) 376 char *strcat(char *restrict s1, const char *restrict s2); 377 378 #endif /* VARIANT */ 379 380 381 void strcat_null_dst(char *x) { 382 strcat(NULL, x); // expected-warning{{Null pointer argument in call to string copy function}} 383 } 384 385 void strcat_null_src(char *x) { 386 strcat(x, NULL); // expected-warning{{Null pointer argument in call to string copy function}} 387 } 388 389 void strcat_fn(char *x) { 390 strcat(x, (char*)&strcat_fn); // expected-warning{{Argument to string copy function is the address of the function 'strcat_fn', which is not a null-terminated string}} 391 } 392 393 void strcat_effects(char *y) { 394 char x[8] = "123"; 395 size_t orig_len = strlen(x); 396 char a = x[0]; 397 398 if (strlen(y) != 4) 399 return; 400 401 clang_analyzer_eval(strcat(x, y) == x); // expected-warning{{TRUE}} 402 clang_analyzer_eval((int)strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}} 403 } 404 405 void strcat_overflow_0(char *y) { 406 char x[4] = "12"; 407 if (strlen(y) == 4) 408 strcat(x, y); // expected-warning{{String copy function overflows destination buffer}} 409 } 410 411 void strcat_overflow_1(char *y) { 412 char x[4] = "12"; 413 if (strlen(y) == 3) 414 strcat(x, y); // expected-warning{{String copy function overflows destination buffer}} 415 } 416 417 void strcat_overflow_2(char *y) { 418 char x[4] = "12"; 419 if (strlen(y) == 2) 420 strcat(x, y); // expected-warning{{String copy function overflows destination buffer}} 421 } 422 423 void strcat_no_overflow(char *y) { 424 char x[5] = "12"; 425 if (strlen(y) == 2) 426 strcat(x, y); // no-warning 427 } 428 429 void strcat_symbolic_dst_length(char *dst) { 430 strcat(dst, "1234"); 431 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 432 } 433 434 void strcat_symbolic_dst_length_taint(char *dst) { 435 scanf("%s", dst); // Taint data. 436 strcat(dst, "1234"); 437 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 438 } 439 440 void strcat_unknown_src_length(char *src, int offset) { 441 char dst[8] = "1234"; 442 strcat(dst, &src[offset]); 443 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 444 } 445 446 // There is no strcat_unknown_dst_length because if we can't get a symbolic 447 // length for the "before" strlen, we won't be able to set one for "after". 448 449 void strcat_too_big(char *dst, char *src) { 450 // We assume this can never actually happen, so we don't get a warning. 451 if (strlen(dst) != (((size_t)0) - 2)) 452 return; 453 if (strlen(src) != 2) 454 return; 455 strcat(dst, src); 456 } 457 458 459 //===----------------------------------------------------------------------=== 460 // strncpy() 461 //===----------------------------------------------------------------------=== 462 463 #ifdef VARIANT 464 465 #define __strncpy_chk BUILTIN(__strncpy_chk) 466 char *__strncpy_chk(char *restrict s1, const char *restrict s2, size_t n, size_t destlen); 467 468 #define strncpy(a,b,n) __strncpy_chk(a,b,n,(size_t)-1) 469 470 #else /* VARIANT */ 471 472 #define strncpy BUILTIN(strncpy) 473 char *strncpy(char *restrict s1, const char *restrict s2, size_t n); 474 475 #endif /* VARIANT */ 476 477 478 void strncpy_null_dst(char *x) { 479 strncpy(NULL, x, 5); // expected-warning{{Null pointer argument in call to string copy function}} 480 } 481 482 void strncpy_null_src(char *x) { 483 strncpy(x, NULL, 5); // expected-warning{{Null pointer argument in call to string copy function}} 484 } 485 486 void strncpy_fn(char *x) { 487 strncpy(x, (char*)&strcpy_fn, 5); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}} 488 } 489 490 void strncpy_effects(char *x, char *y) { 491 char a = x[0]; 492 493 clang_analyzer_eval(strncpy(x, y, 5) == x); // expected-warning{{TRUE}} 494 clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{UNKNOWN}} 495 clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}} 496 } 497 498 void strncpy_overflow(char *y) { 499 char x[4]; 500 if (strlen(y) == 4) 501 strncpy(x, y, 5); // expected-warning{{Size argument is greater than the length of the destination buffer}} 502 } 503 504 void strncpy_no_overflow(char *y) { 505 char x[4]; 506 if (strlen(y) == 3) 507 strncpy(x, y, 5); // expected-warning{{Size argument is greater than the length of the destination buffer}} 508 } 509 510 void strncpy_no_overflow2(char *y, int n) { 511 if (n <= 4) 512 return; 513 514 char x[4]; 515 if (strlen(y) == 3) 516 strncpy(x, y, n); // expected-warning{{Size argument is greater than the length of the destination buffer}} 517 } 518 519 void strncpy_truncate(char *y) { 520 char x[4]; 521 if (strlen(y) == 4) 522 strncpy(x, y, 3); // no-warning 523 } 524 525 void strncpy_no_truncate(char *y) { 526 char x[4]; 527 if (strlen(y) == 3) 528 strncpy(x, y, 3); // no-warning 529 } 530 531 void strncpy_exactly_matching_buffer(char *y) { 532 char x[4]; 533 strncpy(x, y, 4); // no-warning 534 535 // strncpy does not null-terminate, so we have no idea what the strlen is 536 // after this. 537 clang_analyzer_eval(strlen(x) > 4); // expected-warning{{UNKNOWN}} 538 } 539 540 void strncpy_zero(char *src) { 541 char dst[] = "123"; 542 strncpy(dst, src, 0); // no-warning 543 } 544 545 void strncpy_empty() { 546 char dst[] = "123"; 547 char src[] = ""; 548 strncpy(dst, src, 4); // no-warning 549 } 550 551 //===----------------------------------------------------------------------=== 552 // strncat() 553 //===----------------------------------------------------------------------=== 554 555 #ifdef VARIANT 556 557 #define __strncat_chk BUILTIN(__strncat_chk) 558 char *__strncat_chk(char *restrict s1, const char *restrict s2, size_t n, size_t destlen); 559 560 #define strncat(a,b,c) __strncat_chk(a,b,c, (size_t)-1) 561 562 #else /* VARIANT */ 563 564 #define strncat BUILTIN(strncat) 565 char *strncat(char *restrict s1, const char *restrict s2, size_t n); 566 567 #endif /* VARIANT */ 568 569 570 void strncat_null_dst(char *x) { 571 strncat(NULL, x, 4); // expected-warning{{Null pointer argument in call to string copy function}} 572 } 573 574 void strncat_null_src(char *x) { 575 strncat(x, NULL, 4); // expected-warning{{Null pointer argument in call to string copy function}} 576 } 577 578 void strncat_fn(char *x) { 579 strncat(x, (char*)&strncat_fn, 4); // expected-warning{{Argument to string copy function is the address of the function 'strncat_fn', which is not a null-terminated string}} 580 } 581 582 void strncat_effects(char *y) { 583 char x[8] = "123"; 584 size_t orig_len = strlen(x); 585 char a = x[0]; 586 587 if (strlen(y) != 4) 588 return; 589 590 clang_analyzer_eval(strncat(x, y, strlen(y)) == x); // expected-warning{{TRUE}} 591 clang_analyzer_eval(strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}} 592 } 593 594 void strncat_overflow_0(char *y) { 595 char x[4] = "12"; 596 if (strlen(y) == 4) 597 strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}} 598 } 599 600 void strncat_overflow_1(char *y) { 601 char x[4] = "12"; 602 if (strlen(y) == 3) 603 strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}} 604 } 605 606 void strncat_overflow_2(char *y) { 607 char x[4] = "12"; 608 if (strlen(y) == 2) 609 strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}} 610 } 611 612 void strncat_overflow_3(char *y) { 613 char x[4] = "12"; 614 if (strlen(y) == 4) 615 strncat(x, y, 2); // expected-warning{{Size argument is greater than the free space in the destination buffer}} 616 } 617 void strncat_no_overflow_1(char *y) { 618 char x[5] = "12"; 619 if (strlen(y) == 2) 620 strncat(x, y, strlen(y)); // no-warning 621 } 622 623 void strncat_no_overflow_2(char *y) { 624 char x[4] = "12"; 625 if (strlen(y) == 4) 626 strncat(x, y, 1); // no-warning 627 } 628 629 void strncat_symbolic_dst_length(char *dst) { 630 strncat(dst, "1234", 5); 631 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 632 } 633 634 void strncat_symbolic_src_length(char *src) { 635 char dst[8] = "1234"; 636 strncat(dst, src, 3); 637 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 638 639 char dst2[8] = "1234"; 640 strncat(dst2, src, 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}} 641 } 642 643 void strncat_unknown_src_length(char *src, int offset) { 644 char dst[8] = "1234"; 645 strncat(dst, &src[offset], 3); 646 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 647 648 char dst2[8] = "1234"; 649 strncat(dst2, &src[offset], 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}} 650 } 651 652 // There is no strncat_unknown_dst_length because if we can't get a symbolic 653 // length for the "before" strlen, we won't be able to set one for "after". 654 655 void strncat_symbolic_limit(unsigned limit) { 656 char dst[6] = "1234"; 657 char src[] = "567"; 658 strncat(dst, src, limit); // no-warning 659 660 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 661 clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}} 662 } 663 664 void strncat_unknown_limit(float limit) { 665 char dst[6] = "1234"; 666 char src[] = "567"; 667 strncat(dst, src, (size_t)limit); // no-warning 668 669 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 670 clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}} 671 } 672 673 void strncat_too_big(char *dst, char *src) { 674 // We assume this will never actually happen, so we don't get a warning. 675 if (strlen(dst) != (((size_t)0) - 2)) 676 return; 677 if (strlen(src) != 2) 678 return; 679 strncat(dst, src, 2); 680 } 681 682 void strncat_zero(char *src) { 683 char dst[] = "123"; 684 strncat(dst, src, 0); // no-warning 685 } 686 687 void strncat_empty() { 688 char dst[8] = "123"; 689 char src[] = ""; 690 strncat(dst, src, 4); // no-warning 691 } 692 693 //===----------------------------------------------------------------------=== 694 // strcmp() 695 //===----------------------------------------------------------------------=== 696 697 #define strcmp BUILTIN(strcmp) 698 int strcmp(const char * s1, const char * s2); 699 700 void strcmp_check_modelling() { 701 char *x = "aa"; 702 char *y = "a"; 703 clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}} 704 clang_analyzer_eval(strcmp(x, y) <= 0); // expected-warning{{FALSE}} 705 clang_analyzer_eval(strcmp(x, y) > 1); // expected-warning{{UNKNOWN}} 706 707 clang_analyzer_eval(strcmp(y, x) < 0); // expected-warning{{TRUE}} 708 clang_analyzer_eval(strcmp(y, x) >= 0); // expected-warning{{FALSE}} 709 clang_analyzer_eval(strcmp(y, x) < -1); // expected-warning{{UNKNOWN}} 710 } 711 712 void strcmp_constant0() { 713 clang_analyzer_eval(strcmp("123", "123") == 0); // expected-warning{{TRUE}} 714 } 715 716 void strcmp_constant_and_var_0() { 717 char *x = "123"; 718 clang_analyzer_eval(strcmp(x, "123") == 0); // expected-warning{{TRUE}} 719 } 720 721 void strcmp_constant_and_var_1() { 722 char *x = "123"; 723 clang_analyzer_eval(strcmp("123", x) == 0); // expected-warning{{TRUE}} 724 } 725 726 void strcmp_0() { 727 char *x = "123"; 728 char *y = "123"; 729 clang_analyzer_eval(strcmp(x, y) == 0); // expected-warning{{TRUE}} 730 } 731 732 void strcmp_1() { 733 char *x = "234"; 734 char *y = "123"; 735 clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}} 736 } 737 738 void strcmp_2() { 739 char *x = "123"; 740 char *y = "234"; 741 clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}} 742 } 743 744 void strcmp_null_0() { 745 char *x = NULL; 746 char *y = "123"; 747 strcmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}} 748 } 749 750 void strcmp_null_1() { 751 char *x = "123"; 752 char *y = NULL; 753 strcmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}} 754 } 755 756 void strcmp_diff_length_0() { 757 char *x = "12345"; 758 char *y = "234"; 759 clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}} 760 } 761 762 void strcmp_diff_length_1() { 763 char *x = "123"; 764 char *y = "23456"; 765 clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}} 766 } 767 768 void strcmp_diff_length_2() { 769 char *x = "12345"; 770 char *y = "123"; 771 clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}} 772 } 773 774 void strcmp_diff_length_3() { 775 char *x = "123"; 776 char *y = "12345"; 777 clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}} 778 } 779 780 void strcmp_embedded_null () { 781 clang_analyzer_eval(strcmp("\0z", "\0y") == 0); // expected-warning{{TRUE}} 782 } 783 784 void strcmp_unknown_arg (char *unknown) { 785 clang_analyzer_eval(strcmp(unknown, unknown) == 0); // expected-warning{{TRUE}} 786 } 787 788 union argument { 789 char *f; 790 }; 791 792 void function_pointer_cast_helper(char **a) { 793 strcmp("Hi", *a); // PR24951 crash 794 } 795 796 void strcmp_union_function_pointer_cast(union argument a) { 797 void (*fPtr)(union argument *) = (void (*)(union argument *))function_pointer_cast_helper; 798 799 fPtr(&a); 800 } 801 802 //===----------------------------------------------------------------------=== 803 // strncmp() 804 //===----------------------------------------------------------------------=== 805 806 #define strncmp BUILTIN(strncmp) 807 int strncmp(const char *s1, const char *s2, size_t n); 808 809 void strncmp_check_modelling() { 810 char *x = "aa"; 811 char *y = "a"; 812 clang_analyzer_eval(strncmp(x, y, 2) > 0); // expected-warning{{TRUE}} 813 clang_analyzer_eval(strncmp(x, y, 2) <= 0); // expected-warning{{FALSE}} 814 clang_analyzer_eval(strncmp(x, y, 2) > 1); // expected-warning{{UNKNOWN}} 815 816 clang_analyzer_eval(strncmp(y, x, 2) < 0); // expected-warning{{TRUE}} 817 clang_analyzer_eval(strncmp(y, x, 2) >= 0); // expected-warning{{FALSE}} 818 clang_analyzer_eval(strncmp(y, x, 2) < -1); // expected-warning{{UNKNOWN}} 819 } 820 821 void strncmp_constant0() { 822 clang_analyzer_eval(strncmp("123", "123", 3) == 0); // expected-warning{{TRUE}} 823 } 824 825 void strncmp_constant_and_var_0() { 826 char *x = "123"; 827 clang_analyzer_eval(strncmp(x, "123", 3) == 0); // expected-warning{{TRUE}} 828 } 829 830 void strncmp_constant_and_var_1() { 831 char *x = "123"; 832 clang_analyzer_eval(strncmp("123", x, 3) == 0); // expected-warning{{TRUE}} 833 } 834 835 void strncmp_0() { 836 char *x = "123"; 837 char *y = "123"; 838 clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}} 839 } 840 841 void strncmp_1() { 842 char *x = "234"; 843 char *y = "123"; 844 clang_analyzer_eval(strncmp(x, y, 3) > 0); // expected-warning{{TRUE}} 845 } 846 847 void strncmp_2() { 848 char *x = "123"; 849 char *y = "234"; 850 clang_analyzer_eval(strncmp(x, y, 3) < 0); // expected-warning{{TRUE}} 851 } 852 853 void strncmp_null_0() { 854 char *x = NULL; 855 char *y = "123"; 856 strncmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}} 857 } 858 859 void strncmp_null_1() { 860 char *x = "123"; 861 char *y = NULL; 862 strncmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}} 863 } 864 865 void strncmp_diff_length_0() { 866 char *x = "12345"; 867 char *y = "234"; 868 clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}} 869 } 870 871 void strncmp_diff_length_1() { 872 char *x = "123"; 873 char *y = "23456"; 874 clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}} 875 } 876 877 void strncmp_diff_length_2() { 878 char *x = "12345"; 879 char *y = "123"; 880 clang_analyzer_eval(strncmp(x, y, 5) > 0); // expected-warning{{TRUE}} 881 } 882 883 void strncmp_diff_length_3() { 884 char *x = "123"; 885 char *y = "12345"; 886 clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}} 887 } 888 889 void strncmp_diff_length_4() { 890 char *x = "123"; 891 char *y = "12345"; 892 clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}} 893 } 894 895 void strncmp_diff_length_5() { 896 char *x = "012"; 897 char *y = "12345"; 898 clang_analyzer_eval(strncmp(x, y, 3) < 0); // expected-warning{{TRUE}} 899 } 900 901 void strncmp_diff_length_6() { 902 char *x = "234"; 903 char *y = "12345"; 904 clang_analyzer_eval(strncmp(x, y, 3) > 0); // expected-warning{{TRUE}} 905 } 906 907 void strncmp_embedded_null () { 908 clang_analyzer_eval(strncmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}} 909 } 910 911 //===----------------------------------------------------------------------=== 912 // strcasecmp() 913 //===----------------------------------------------------------------------=== 914 915 #define strcasecmp BUILTIN(strcasecmp) 916 int strcasecmp(const char *s1, const char *s2); 917 918 void strcasecmp_check_modelling() { 919 char *x = "aa"; 920 char *y = "a"; 921 clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}} 922 clang_analyzer_eval(strcasecmp(x, y) <= 0); // expected-warning{{FALSE}} 923 clang_analyzer_eval(strcasecmp(x, y) > 1); // expected-warning{{UNKNOWN}} 924 925 clang_analyzer_eval(strcasecmp(y, x) < 0); // expected-warning{{TRUE}} 926 clang_analyzer_eval(strcasecmp(y, x) >= 0); // expected-warning{{FALSE}} 927 clang_analyzer_eval(strcasecmp(y, x) < -1); // expected-warning{{UNKNOWN}} 928 } 929 930 void strcasecmp_constant0() { 931 clang_analyzer_eval(strcasecmp("abc", "Abc") == 0); // expected-warning{{TRUE}} 932 } 933 934 void strcasecmp_constant_and_var_0() { 935 char *x = "abc"; 936 clang_analyzer_eval(strcasecmp(x, "Abc") == 0); // expected-warning{{TRUE}} 937 } 938 939 void strcasecmp_constant_and_var_1() { 940 char *x = "abc"; 941 clang_analyzer_eval(strcasecmp("Abc", x) == 0); // expected-warning{{TRUE}} 942 } 943 944 void strcasecmp_0() { 945 char *x = "abc"; 946 char *y = "Abc"; 947 clang_analyzer_eval(strcasecmp(x, y) == 0); // expected-warning{{TRUE}} 948 } 949 950 void strcasecmp_1() { 951 char *x = "Bcd"; 952 char *y = "abc"; 953 clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}} 954 } 955 956 void strcasecmp_2() { 957 char *x = "abc"; 958 char *y = "Bcd"; 959 clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}} 960 } 961 962 void strcasecmp_null_0() { 963 char *x = NULL; 964 char *y = "123"; 965 strcasecmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}} 966 } 967 968 void strcasecmp_null_1() { 969 char *x = "123"; 970 char *y = NULL; 971 strcasecmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}} 972 } 973 974 void strcasecmp_diff_length_0() { 975 char *x = "abcde"; 976 char *y = "aBd"; 977 clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}} 978 } 979 980 void strcasecmp_diff_length_1() { 981 char *x = "abc"; 982 char *y = "aBdef"; 983 clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}} 984 } 985 986 void strcasecmp_diff_length_2() { 987 char *x = "aBcDe"; 988 char *y = "abc"; 989 clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}} 990 } 991 992 void strcasecmp_diff_length_3() { 993 char *x = "aBc"; 994 char *y = "abcde"; 995 clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}} 996 } 997 998 void strcasecmp_embedded_null () { 999 clang_analyzer_eval(strcasecmp("ab\0zz", "ab\0yy") == 0); // expected-warning{{TRUE}} 1000 } 1001 1002 //===----------------------------------------------------------------------=== 1003 // strncasecmp() 1004 //===----------------------------------------------------------------------=== 1005 1006 #define strncasecmp BUILTIN(strncasecmp) 1007 int strncasecmp(const char *s1, const char *s2, size_t n); 1008 1009 void strncasecmp_check_modelling() { 1010 char *x = "aa"; 1011 char *y = "a"; 1012 clang_analyzer_eval(strncasecmp(x, y, 2) > 0); // expected-warning{{TRUE}} 1013 clang_analyzer_eval(strncasecmp(x, y, 2) <= 0); // expected-warning{{FALSE}} 1014 clang_analyzer_eval(strncasecmp(x, y, 2) > 1); // expected-warning{{UNKNOWN}} 1015 1016 clang_analyzer_eval(strncasecmp(y, x, 2) < 0); // expected-warning{{TRUE}} 1017 clang_analyzer_eval(strncasecmp(y, x, 2) >= 0); // expected-warning{{FALSE}} 1018 clang_analyzer_eval(strncasecmp(y, x, 2) < -1); // expected-warning{{UNKNOWN}} 1019 } 1020 1021 void strncasecmp_constant0() { 1022 clang_analyzer_eval(strncasecmp("abc", "Abc", 3) == 0); // expected-warning{{TRUE}} 1023 } 1024 1025 void strncasecmp_constant_and_var_0() { 1026 char *x = "abc"; 1027 clang_analyzer_eval(strncasecmp(x, "Abc", 3) == 0); // expected-warning{{TRUE}} 1028 } 1029 1030 void strncasecmp_constant_and_var_1() { 1031 char *x = "abc"; 1032 clang_analyzer_eval(strncasecmp("Abc", x, 3) == 0); // expected-warning{{TRUE}} 1033 } 1034 1035 void strncasecmp_0() { 1036 char *x = "abc"; 1037 char *y = "Abc"; 1038 clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}} 1039 } 1040 1041 void strncasecmp_1() { 1042 char *x = "Bcd"; 1043 char *y = "abc"; 1044 clang_analyzer_eval(strncasecmp(x, y, 3) > 0); // expected-warning{{TRUE}} 1045 } 1046 1047 void strncasecmp_2() { 1048 char *x = "abc"; 1049 char *y = "Bcd"; 1050 clang_analyzer_eval(strncasecmp(x, y, 3) < 0); // expected-warning{{TRUE}} 1051 } 1052 1053 void strncasecmp_null_0() { 1054 char *x = NULL; 1055 char *y = "123"; 1056 strncasecmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}} 1057 } 1058 1059 void strncasecmp_null_1() { 1060 char *x = "123"; 1061 char *y = NULL; 1062 strncasecmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}} 1063 } 1064 1065 void strncasecmp_diff_length_0() { 1066 char *x = "abcde"; 1067 char *y = "aBd"; 1068 clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}} 1069 } 1070 1071 void strncasecmp_diff_length_1() { 1072 char *x = "abc"; 1073 char *y = "aBdef"; 1074 clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}} 1075 } 1076 1077 void strncasecmp_diff_length_2() { 1078 char *x = "aBcDe"; 1079 char *y = "abc"; 1080 clang_analyzer_eval(strncasecmp(x, y, 5) > 0); // expected-warning{{TRUE}} 1081 } 1082 1083 void strncasecmp_diff_length_3() { 1084 char *x = "aBc"; 1085 char *y = "abcde"; 1086 clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}} 1087 } 1088 1089 void strncasecmp_diff_length_4() { 1090 char *x = "abcde"; 1091 char *y = "aBc"; 1092 clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}} 1093 } 1094 1095 void strncasecmp_diff_length_5() { 1096 char *x = "abcde"; 1097 char *y = "aBd"; 1098 clang_analyzer_eval(strncasecmp(x, y, 3) < 0); // expected-warning{{TRUE}} 1099 } 1100 1101 void strncasecmp_diff_length_6() { 1102 char *x = "aBDe"; 1103 char *y = "abc"; 1104 clang_analyzer_eval(strncasecmp(x, y, 3) > 0); // expected-warning{{TRUE}} 1105 } 1106 1107 void strncasecmp_embedded_null () { 1108 clang_analyzer_eval(strncasecmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}} 1109 } 1110 1111 //===----------------------------------------------------------------------=== 1112 // strsep() 1113 //===----------------------------------------------------------------------=== 1114 1115 char *strsep(char **stringp, const char *delim); 1116 1117 void strsep_null_delim(char *s) { 1118 strsep(&s, NULL); // expected-warning{{Null pointer argument in call to strsep()}} 1119 } 1120 1121 void strsep_null_search() { 1122 strsep(NULL, ""); // expected-warning{{Null pointer argument in call to strsep()}} 1123 } 1124 1125 void strsep_return_original_pointer(char *s) { 1126 char *original = s; 1127 char *result = strsep(&s, ""); // no-warning 1128 clang_analyzer_eval(original == result); // expected-warning{{TRUE}} 1129 } 1130 1131 void strsep_null_string() { 1132 char *s = NULL; 1133 char *result = strsep(&s, ""); // no-warning 1134 clang_analyzer_eval(result == NULL); // expected-warning{{TRUE}} 1135 } 1136 1137 void strsep_changes_input_pointer(char *s) { 1138 char *original = s; 1139 strsep(&s, ""); // no-warning 1140 clang_analyzer_eval(s == original); // expected-warning{{UNKNOWN}} 1141 clang_analyzer_eval(s == NULL); // expected-warning{{UNKNOWN}} 1142 1143 // Check that the value is symbolic. 1144 if (s == NULL) { 1145 clang_analyzer_eval(s == NULL); // expected-warning{{TRUE}} 1146 } 1147 } 1148 1149 void strsep_changes_input_string() { 1150 char str[] = "abc"; 1151 1152 clang_analyzer_eval(str[1] == 'b'); // expected-warning{{TRUE}} 1153 1154 char *s = str; 1155 strsep(&s, "b"); // no-warning 1156 1157 // The real strsep will change the first delimiter it finds into a NUL 1158 // character. For now, we just model the invalidation. 1159 clang_analyzer_eval(str[1] == 'b'); // expected-warning{{UNKNOWN}} 1160 } 1161 1162 //===----------------------------------------------------------------------=== 1163 // FIXMEs 1164 //===----------------------------------------------------------------------=== 1165 1166 // The analyzer_eval call below should evaluate to true. We are being too 1167 // aggressive in marking the (length of) src symbol dead. The length of dst 1168 // depends on src. This could be explicitely specified in the checker or the 1169 // logic for handling MetadataSymbol in SymbolManager needs to change. 1170 void strcat_symbolic_src_length(char *src) { 1171 char dst[8] = "1234"; 1172 strcat(dst, src); 1173 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{UNKNOWN}} 1174 } 1175 1176 // The analyzer_eval call below should evaluate to true. Most likely the same 1177 // issue as the test above. 1178 void strncpy_exactly_matching_buffer2(char *y) { 1179 if (strlen(y) >= 4) 1180 return; 1181 1182 char x[4]; 1183 strncpy(x, y, 4); // no-warning 1184 1185 // This time, we know that y fits in x anyway. 1186 clang_analyzer_eval(strlen(x) <= 3); // expected-warning{{UNKNOWN}} 1187 } 1188