1 // RUN: %clang_analyze_cc1 -verify %s -Wno-null-dereference \ 2 // RUN: -analyzer-checker=core \ 3 // RUN: -analyzer-checker=unix.cstring \ 4 // RUN: -analyzer-checker=unix.Malloc \ 5 // RUN: -analyzer-checker=alpha.unix.cstring \ 6 // RUN: -analyzer-checker=debug.ExprInspection \ 7 // RUN: -analyzer-config eagerly-assume=false 8 // 9 // RUN: %clang_analyze_cc1 -verify %s -Wno-null-dereference -DUSE_BUILTINS \ 10 // RUN: -analyzer-checker=core \ 11 // RUN: -analyzer-checker=unix.cstring \ 12 // RUN: -analyzer-checker=unix.Malloc \ 13 // RUN: -analyzer-checker=alpha.unix.cstring \ 14 // RUN: -analyzer-checker=debug.ExprInspection \ 15 // RUN: -analyzer-config eagerly-assume=false 16 // 17 // RUN: %clang_analyze_cc1 -verify %s -Wno-null-dereference -DVARIANT \ 18 // RUN: -analyzer-checker=core \ 19 // RUN: -analyzer-checker=unix.cstring \ 20 // RUN: -analyzer-checker=unix.Malloc \ 21 // RUN: -analyzer-checker=alpha.unix.cstring \ 22 // RUN: -analyzer-checker=debug.ExprInspection \ 23 // RUN: -analyzer-config eagerly-assume=false 24 // 25 // RUN: %clang_analyze_cc1 -verify %s -Wno-null-dereference \ 26 // RUN: -DUSE_BUILTINS -DVARIANT \ 27 // RUN: -analyzer-checker=core \ 28 // RUN: -analyzer-checker=optin.taint \ 29 // RUN: -analyzer-checker=unix.cstring \ 30 // RUN: -analyzer-checker=unix.Malloc \ 31 // RUN: -analyzer-checker=alpha.unix.cstring \ 32 // RUN: -analyzer-checker=debug.ExprInspection \ 33 // RUN: -analyzer-config eagerly-assume=false 34 // 35 // RUN: %clang_analyze_cc1 -verify %s -Wno-null-dereference \ 36 // RUN: -DSUPPRESS_OUT_OF_BOUND \ 37 // RUN: -analyzer-checker=core \ 38 // RUN: -analyzer-checker=unix.cstring \ 39 // RUN: -analyzer-checker=unix.Malloc \ 40 // RUN: -analyzer-checker=alpha.unix.cstring.BufferOverlap \ 41 // RUN: -analyzer-checker=unix.cstring.NotNullTerminated \ 42 // RUN: -analyzer-checker=debug.ExprInspection \ 43 // RUN: -analyzer-config eagerly-assume=false 44 45 //===----------------------------------------------------------------------=== 46 // Declarations 47 //===----------------------------------------------------------------------=== 48 49 // Some functions are so similar to each other that they follow the same code 50 // path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is 51 // defined, make sure to use the variants instead to make sure they are still 52 // checked by the analyzer. 53 54 // Some functions are implemented as builtins. These should be #defined as 55 // BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined. 56 57 // Functions that have variants and are also available as builtins should be 58 // declared carefully! See memcpy() for an example. 59 60 #ifdef USE_BUILTINS 61 # define BUILTIN(f) __builtin_ ## f 62 #else /* USE_BUILTINS */ 63 # define BUILTIN(f) f 64 #endif /* USE_BUILTINS */ 65 66 #define NULL 0 67 typedef typeof(sizeof(int)) size_t; 68 69 void clang_analyzer_eval(int); 70 71 int scanf(const char *restrict format, ...); 72 void *malloc(size_t); 73 void free(void *); 74 void *memcpy(void *restrict dest, const void *restrict src, size_t n); 75 76 //===----------------------------------------------------------------------=== 77 // strlen() 78 //===----------------------------------------------------------------------=== 79 80 #define strlen BUILTIN(strlen) 81 size_t strlen(const char *s); 82 83 void strlen_constant0(void) { 84 clang_analyzer_eval(strlen("123") == 3); // expected-warning{{TRUE}} 85 } 86 87 void strlen_constant1(void) { 88 const char *a = "123"; 89 clang_analyzer_eval(strlen(a) == 3); // expected-warning{{TRUE}} 90 } 91 92 void strlen_constant2(char x) { 93 char a[] = "123"; 94 clang_analyzer_eval(strlen(a) == 3); // expected-warning{{TRUE}} 95 96 a[0] = x; 97 clang_analyzer_eval(strlen(a) == 3); // expected-warning{{UNKNOWN}} 98 } 99 100 const char *const global_str_ptr = "abcd"; 101 const char global_str_arr[] = "efgh"; 102 const char *global_non_const_ptr1 = "ijk"; 103 char *global_non_const_ptr2 = "lmn"; 104 char global_non_const_arr[] = "op"; 105 106 void strlen_global_constant_ptr(void) { 107 clang_analyzer_eval(strlen(global_str_ptr) == 4); // expected-warning{{TRUE}} 108 } 109 110 void strlen_global_constant_arr(void) { 111 clang_analyzer_eval(strlen(global_str_arr) == 4); // expected-warning{{TRUE}} 112 } 113 114 void strlen_global_non_const_ptr(void) { 115 clang_analyzer_eval(strlen(global_non_const_ptr1) == 3); // expected-warning{{UNKNOWN}} 116 clang_analyzer_eval(strlen(global_non_const_ptr2) == 3); // expected-warning{{UNKNOWN}} 117 } 118 119 void strlen_global_non_const_arr(void) { 120 clang_analyzer_eval(strlen(global_non_const_arr) == 2); // expected-warning{{UNKNOWN}} 121 } 122 123 size_t strlen_null(void) { 124 return strlen(0); // expected-warning{{Null pointer passed as 1st argument to string length function}} 125 } 126 127 size_t strlen_fn(void) { 128 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}} 129 } 130 131 size_t strlen_nonloc(void) { 132 label: 133 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}} 134 } 135 136 void strlen_subregion(void) { 137 struct two_strings { char a[2], b[2]; }; 138 extern void use_two_strings(struct two_strings *); 139 140 struct two_strings z; 141 use_two_strings(&z); 142 143 size_t a = strlen(z.a); 144 z.b[0] = 5; 145 size_t b = strlen(z.a); 146 if (a == 0) 147 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} 148 149 use_two_strings(&z); 150 151 size_t c = strlen(z.a); 152 if (a == 0) 153 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 154 } 155 156 extern void use_string(char *); 157 void strlen_argument(char *x) { 158 size_t a = strlen(x); 159 size_t b = strlen(x); 160 if (a == 0) 161 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} 162 163 use_string(x); 164 165 size_t c = strlen(x); 166 if (a == 0) 167 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 168 } 169 170 extern char global_str[]; 171 void strlen_global(void) { 172 size_t a = strlen(global_str); 173 size_t b = strlen(global_str); 174 if (a == 0) { 175 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} 176 // Make sure clang_analyzer_eval does not invalidate globals. 177 clang_analyzer_eval(strlen(global_str) == 0); // expected-warning{{TRUE}} 178 } 179 180 // Call a function with unknown effects, which should invalidate globals. 181 use_string(0); 182 183 size_t c = strlen(global_str); 184 if (a == 0) 185 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 186 } 187 188 void strlen_indirect(char *x) { 189 size_t a = strlen(x); 190 char *p = x; 191 char **p2 = &p; 192 size_t b = strlen(x); 193 if (a == 0) 194 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} 195 196 extern void use_string_ptr(char*const*); 197 use_string_ptr(p2); 198 199 size_t c = strlen(x); 200 if (a == 0) 201 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 202 } 203 204 void strlen_indirect2(char *x) { 205 size_t a = strlen(x); 206 char *p = x; 207 char **p2 = &p; 208 extern void use_string_ptr2(char**); 209 use_string_ptr2(p2); 210 211 size_t c = strlen(x); 212 if (a == 0) 213 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} 214 } 215 216 void strlen_liveness(const char *x) { 217 if (strlen(x) < 5) 218 return; 219 clang_analyzer_eval(strlen(x) < 5); // expected-warning{{FALSE}} 220 } 221 222 223 size_t strlenWrapper(const char *str) { 224 return strlen(str); 225 } 226 227 extern void invalidate(char *s); 228 229 void testStrlenCallee(void) { 230 char str[42]; 231 invalidate(str); 232 size_t lenBefore = strlenWrapper(str); 233 invalidate(str); 234 size_t lenAfter = strlenWrapper(str); 235 clang_analyzer_eval(lenBefore == lenAfter); // expected-warning{{UNKNOWN}} 236 } 237 238 239 //===----------------------------------------------------------------------=== 240 // strnlen() 241 //===----------------------------------------------------------------------=== 242 243 size_t strnlen(const char *s, size_t maxlen); 244 245 void strnlen_constant0(void) { 246 clang_analyzer_eval(strnlen("123", 10) == 3); // expected-warning{{TRUE}} 247 } 248 249 void strnlen_constant1(void) { 250 const char *a = "123"; 251 clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{TRUE}} 252 } 253 254 void strnlen_constant2(char x) { 255 char a[] = "123"; 256 clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{TRUE}} 257 a[0] = x; 258 clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{UNKNOWN}} 259 } 260 261 void strnlen_constant4(void) { 262 clang_analyzer_eval(strnlen("123456", 3) == 3); // expected-warning{{TRUE}} 263 } 264 265 void strnlen_constant5(void) { 266 const char *a = "123456"; 267 clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{TRUE}} 268 } 269 270 void strnlen_constant6(char x) { 271 char a[] = "123456"; 272 clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{TRUE}} 273 a[0] = x; 274 clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{UNKNOWN}} 275 } 276 277 size_t strnlen_null(void) { 278 return strnlen(0, 3); // expected-warning{{Null pointer passed as 1st argument to string length function}} 279 } 280 281 size_t strnlen_fn(void) { 282 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}} 283 } 284 285 size_t strnlen_nonloc(void) { 286 label: 287 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}} 288 } 289 290 void strnlen_zero(void) { 291 clang_analyzer_eval(strnlen("abc", 0) == 0); // expected-warning{{TRUE}} 292 clang_analyzer_eval(strnlen(NULL, 0) == 0); // expected-warning{{TRUE}} 293 } 294 295 size_t strnlen_compound_literal(void) { 296 // This used to crash because we don't model the string lengths of 297 // compound literals. 298 return strnlen((char[]) { 'a', 'b', 0 }, 1); 299 } 300 301 size_t strnlen_unknown_limit(float f) { 302 // This used to crash because we don't model the integer values of floats. 303 return strnlen("abc", (int)f); 304 } 305 306 void strnlen_is_not_strlen(char *x) { 307 clang_analyzer_eval(strnlen(x, 10) == strlen(x)); // expected-warning{{UNKNOWN}} 308 } 309 310 void strnlen_at_limit(char *x) { 311 size_t len = strnlen(x, 10); 312 clang_analyzer_eval(len <= 10); // expected-warning{{TRUE}} 313 clang_analyzer_eval(len == 10); // expected-warning{{UNKNOWN}} 314 clang_analyzer_eval(len < 10); // expected-warning{{UNKNOWN}} 315 } 316 317 void strnlen_at_actual(size_t limit) { 318 size_t len = strnlen("abc", limit); 319 clang_analyzer_eval(len <= 3); // expected-warning{{TRUE}} 320 // This is due to eager assertion in strnlen. 321 if (limit == 0) { 322 clang_analyzer_eval(len == 0); // expected-warning{{TRUE}} 323 } else { 324 clang_analyzer_eval(len == 3); // expected-warning{{UNKNOWN}} 325 clang_analyzer_eval(len < 3); // expected-warning{{UNKNOWN}} 326 } 327 } 328 329 //===----------------------------------------------------------------------=== 330 // strcpy() 331 //===----------------------------------------------------------------------=== 332 333 #ifdef VARIANT 334 335 #define __strcpy_chk BUILTIN(__strcpy_chk) 336 char *__strcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen); 337 338 #define strcpy(a,b) __strcpy_chk(a,b,(size_t)-1) 339 340 #else /* VARIANT */ 341 342 #define strcpy BUILTIN(strcpy) 343 char *strcpy(char *restrict s1, const char *restrict s2); 344 345 #endif /* VARIANT */ 346 347 348 void strcpy_null_dst(char *x) { 349 strcpy(NULL, x); // expected-warning{{Null pointer passed as 1st argument to string copy function}} 350 } 351 352 void strcpy_null_src(char *x) { 353 strcpy(x, NULL); // expected-warning{{Null pointer passed as 2nd argument to string copy function}} 354 } 355 356 void strcpy_fn(char *x) { 357 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}} 358 } 359 360 void strcpy_fn_const(char *x) { 361 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}} 362 } 363 364 void strcpy_fn_dst(const char *x) { 365 strcpy((char*)&strcpy_fn, x); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}} 366 } 367 368 extern int globalInt; 369 void strcpy_effects(char *x, char *y) { 370 char a = x[0]; 371 if (globalInt != 42) 372 return; 373 374 clang_analyzer_eval(strcpy(x, y) == x); // expected-warning{{TRUE}} 375 clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}} 376 clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}} 377 clang_analyzer_eval(globalInt == 42); // expected-warning{{TRUE}} 378 } 379 380 #ifndef SUPPRESS_OUT_OF_BOUND 381 void strcpy_overflow(char *y) { 382 char x[4]; 383 if (strlen(y) == 4) 384 strcpy(x, y); // expected-warning{{String copy function overflows the destination buffer}} 385 } 386 #endif 387 388 void strcpy_no_overflow(char *y) { 389 char x[4]; 390 if (strlen(y) == 3) 391 strcpy(x, y); // no-warning 392 } 393 394 // PR37503 395 void *get_void_ptr(void); 396 char ***type_punned_ptr; 397 void strcpy_no_assertion(char c) { 398 *(unsigned char **)type_punned_ptr = (unsigned char *)(get_void_ptr()); 399 strcpy(**type_punned_ptr, &c); // no-crash 400 } 401 402 // PR49007 403 char f(char ***c, int *i) { 404 *(void **)c = i + 1; 405 return (**c)[0]; // no-crash 406 } 407 408 //===----------------------------------------------------------------------=== 409 // stpcpy() 410 //===----------------------------------------------------------------------=== 411 412 #ifdef VARIANT 413 414 #define __stpcpy_chk BUILTIN(__stpcpy_chk) 415 char *__stpcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen); 416 417 #define stpcpy(a,b) __stpcpy_chk(a,b,(size_t)-1) 418 419 #else /* VARIANT */ 420 421 #define stpcpy BUILTIN(stpcpy) 422 char *stpcpy(char *restrict s1, const char *restrict s2); 423 424 #endif /* VARIANT */ 425 426 427 void stpcpy_effect(char *x, char *y) { 428 char a = x[0]; 429 430 clang_analyzer_eval(stpcpy(x, y) == &x[strlen(y)]); // expected-warning{{TRUE}} 431 clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}} 432 clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}} 433 } 434 435 #ifndef SUPPRESS_OUT_OF_BOUND 436 void stpcpy_overflow(char *y) { 437 char x[4]; 438 if (strlen(y) == 4) 439 stpcpy(x, y); // expected-warning{{String copy function overflows the destination buffer}} 440 } 441 #endif 442 443 void stpcpy_no_overflow(char *y) { 444 char x[4]; 445 if (strlen(y) == 3) 446 stpcpy(x, y); // no-warning 447 } 448 449 //===----------------------------------------------------------------------=== 450 // strcat() 451 //===----------------------------------------------------------------------=== 452 453 #ifdef VARIANT 454 455 #define __strcat_chk BUILTIN(__strcat_chk) 456 char *__strcat_chk(char *restrict s1, const char *restrict s2, size_t destlen); 457 458 #define strcat(a,b) __strcat_chk(a,b,(size_t)-1) 459 460 #else /* VARIANT */ 461 462 #define strcat BUILTIN(strcat) 463 char *strcat(char *restrict s1, const char *restrict s2); 464 465 #endif /* VARIANT */ 466 467 468 void strcat_null_dst(char *x) { 469 strcat(NULL, x); // expected-warning{{Null pointer passed as 1st argument to string concatenation function}} 470 } 471 472 void strcat_null_src(char *x) { 473 strcat(x, NULL); // expected-warning{{Null pointer passed as 2nd argument to string concatenation function}} 474 } 475 476 void strcat_fn_dst(const char *x) { 477 strcat((char*)&strcat_fn_dst, x); // expected-warning{{Argument to string concatenation function is the address of the function 'strcat_fn_dst', which is not a null-terminated string}} 478 } 479 480 void strcat_fn_src(char *x) { 481 strcat(x, (char*)&strcat_fn_src); // expected-warning{{Argument to string concatenation function is the address of the function 'strcat_fn_src', which is not a null-terminated string}} 482 } 483 484 void strcat_label_dst(const char *x) { 485 label: 486 strcat((char*)&&label, x); // expected-warning{{Argument to string concatenation function is the address of the label 'label', which is not a null-terminated string}} 487 } 488 489 void strcat_label_src(char *x) { 490 label: 491 strcat(x, (char*)&&label); // expected-warning{{Argument to string concatenation function is the address of the label 'label', which is not a null-terminated string}} 492 } 493 494 void strcat_effects(char *y) { 495 char x[8] = "123"; 496 size_t orig_len = strlen(x); 497 char a = x[0]; 498 499 if (strlen(y) != 4) 500 return; 501 502 clang_analyzer_eval(strcat(x, y) == x); // expected-warning{{TRUE}} 503 clang_analyzer_eval((int)strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}} 504 } 505 506 #ifndef SUPPRESS_OUT_OF_BOUND 507 void strcat_overflow_0(char *y) { 508 char x[4] = "12"; 509 if (strlen(y) == 4) 510 strcat(x, y); // expected-warning{{String concatenation function overflows the destination buffer}} 511 } 512 513 void strcat_overflow_1(char *y) { 514 char x[4] = "12"; 515 if (strlen(y) == 3) 516 strcat(x, y); // expected-warning{{String concatenation function overflows the destination buffer}} 517 } 518 519 void strcat_overflow_2(char *y) { 520 char x[4] = "12"; 521 if (strlen(y) == 2) 522 strcat(x, y); // expected-warning{{String concatenation function overflows the destination buffer}} 523 } 524 #endif 525 526 void strcat_no_overflow(char *y) { 527 char x[5] = "12"; 528 if (strlen(y) == 2) 529 strcat(x, y); // no-warning 530 } 531 532 void strcat_symbolic_dst_length(char *dst) { 533 strcat(dst, "1234"); 534 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 535 } 536 537 void strcat_symbolic_dst_length_taint(char *dst) { 538 scanf("%s", dst); // Taint data. 539 strcat(dst, "1234"); 540 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 541 } 542 543 void strcat_unknown_src_length(char *src, int offset) { 544 char dst[8] = "1234"; 545 strcat(dst, &src[offset]); 546 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 547 } 548 549 // There is no strcat_unknown_dst_length because if we can't get a symbolic 550 // length for the "before" strlen, we won't be able to set one for "after". 551 552 void strcat_too_big(char *dst, char *src) { 553 // We assume this can never actually happen, so we don't get a warning. 554 if (strlen(dst) != (((size_t)0) - 2)) 555 return; 556 if (strlen(src) != 2) 557 return; 558 strcat(dst, src); 559 } 560 561 562 //===----------------------------------------------------------------------=== 563 // strncpy() 564 //===----------------------------------------------------------------------=== 565 566 #ifdef VARIANT 567 568 #define __strncpy_chk BUILTIN(__strncpy_chk) 569 char *__strncpy_chk(char *restrict s1, const char *restrict s2, size_t n, size_t destlen); 570 571 #define strncpy(a,b,n) __strncpy_chk(a,b,n,(size_t)-1) 572 573 #else /* VARIANT */ 574 575 #define strncpy BUILTIN(strncpy) 576 char *strncpy(char *restrict s1, const char *restrict s2, size_t n); 577 578 #endif /* VARIANT */ 579 580 581 void strncpy_null_dst(char *x) { 582 strncpy(NULL, x, 5); // expected-warning{{Null pointer passed as 1st argument to string copy function}} 583 } 584 585 void strncpy_null_src(char *x) { 586 strncpy(x, NULL, 5); // expected-warning{{Null pointer passed as 2nd argument to string copy function}} 587 } 588 589 void strncpy_fn_src(char *x) { 590 strncpy(x, (char*)&strncpy_fn_src, 5); // expected-warning{{Argument to string copy function is the address of the function 'strncpy_fn_src', which is not a null-terminated string}} 591 } 592 593 void strncpy_fn_dst(const char *x) { 594 strncpy((char*)&strncpy_fn_dst, x, 5); // expected-warning{{Argument to string copy function is the address of the function 'strncpy_fn_dst', which is not a null-terminated string}} 595 } 596 597 void strncpy_effects(char *x, char *y) { 598 char a = x[0]; 599 600 clang_analyzer_eval(strncpy(x, y, 5) == x); // expected-warning{{TRUE}} 601 clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{UNKNOWN}} 602 clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}} 603 } 604 605 #ifndef SUPPRESS_OUT_OF_BOUND 606 // Enabling the malloc checker enables some of the buffer-checking portions 607 // of the C-string checker. 608 void cstringchecker_bounds_nocrash(void) { 609 char *p = malloc(2); 610 strncpy(p, "AAA", sizeof("AAA")); 611 // expected-warning@-1 {{String copy function overflows the destination buffer}} 612 free(p); 613 } 614 615 void strncpy_overflow(char *y) { 616 char x[4]; 617 if (strlen(y) == 4) 618 strncpy(x, y, 5); 619 // expected-warning@-1 {{String copy function overflows the destination buffer}} 620 #ifndef VARIANT 621 // expected-warning@-3 {{size argument is too large; destination buffer has size 4, but size argument is 5}} 622 #endif 623 } 624 625 void strncpy_no_overflow(char *y) { 626 char x[4]; 627 if (strlen(y) == 3) 628 strncpy(x, y, 5); 629 // expected-warning@-1 {{String copy function overflows the destination buffer}} 630 #ifndef VARIANT 631 // expected-warning@-3 {{size argument is too large; destination buffer has size 4, but size argument is 5}} 632 #endif 633 } 634 635 void strncpy_no_overflow2(char *y, int n) { 636 if (n <= 4) 637 return; 638 639 char x[4]; 640 if (strlen(y) == 3) 641 strncpy(x, y, n); 642 // expected-warning@-1 {{String copy function overflows the destination buffer}} 643 } 644 #endif 645 646 void strncpy_truncate(char *y) { 647 char x[4]; 648 if (strlen(y) == 4) 649 strncpy(x, y, 3); // no-warning 650 } 651 652 void strncpy_no_truncate(char *y) { 653 char x[4]; 654 if (strlen(y) == 3) 655 strncpy(x, y, 3); // no-warning 656 } 657 658 void strncpy_exactly_matching_buffer(char *y) { 659 char x[4]; 660 strncpy(x, y, 4); // no-warning 661 662 // strncpy does not null-terminate, so we have no idea what the strlen is 663 // after this. 664 clang_analyzer_eval(strlen(x) > 4); // expected-warning{{UNKNOWN}} 665 } 666 667 void strncpy_zero(char *src) { 668 char dst[] = "123"; 669 strncpy(dst, src, 0); // no-warning 670 } 671 672 void strncpy_empty(void) { 673 char dst[] = "123"; 674 char src[] = ""; 675 strncpy(dst, src, 4); // no-warning 676 } 677 678 //===----------------------------------------------------------------------=== 679 // strncat() 680 //===----------------------------------------------------------------------=== 681 682 #ifdef VARIANT 683 684 #define __strncat_chk BUILTIN(__strncat_chk) 685 char *__strncat_chk(char *restrict s1, const char *restrict s2, size_t n, size_t destlen); 686 687 #define strncat(a,b,c) __strncat_chk(a,b,c, (size_t)-1) 688 689 #else /* VARIANT */ 690 691 #define strncat BUILTIN(strncat) 692 char *strncat(char *restrict s1, const char *restrict s2, size_t n); 693 694 #endif /* VARIANT */ 695 696 697 void strncat_null_dst(char *x) { 698 strncat(NULL, x, 4); // expected-warning{{Null pointer passed as 1st argument to string concatenation function}} 699 } 700 701 void strncat_null_src(char *x) { 702 strncat(x, NULL, 4); // expected-warning{{Null pointer passed as 2nd argument to string concatenation function}} 703 } 704 705 void strncat_fn_src(char *x) { 706 strncat(x, (char*)&strncat_fn_src, 4); // expected-warning{{Argument to string concatenation function is the address of the function 'strncat_fn_src', which is not a null-terminated string}} 707 } 708 709 void strncat_fn_dst(const char *x) { 710 strncat((char*)&strncat_fn_dst, x, 4); // expected-warning{{Argument to string concatenation function is the address of the function 'strncat_fn_dst', which is not a null-terminated string}} 711 } 712 713 void strncat_effects(char *y) { 714 char x[8] = "123"; 715 size_t orig_len = strlen(x); 716 char a = x[0]; 717 718 if (strlen(y) != 4) 719 return; 720 721 clang_analyzer_eval(strncat(x, y, strlen(y)) == x); // expected-warning{{TRUE}} 722 clang_analyzer_eval(strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}} 723 } 724 725 #ifndef SUPPRESS_OUT_OF_BOUND 726 void strncat_overflow_0(char *y) { 727 char x[4] = "12"; 728 if (strlen(y) == 4) 729 strncat(x, y, strlen(y)); 730 // expected-warning@-1 {{String concatenation function overflows the destination buffer}} 731 } 732 733 void strncat_overflow_1(char *y) { 734 char x[4] = "12"; 735 if (strlen(y) == 3) 736 strncat(x, y, strlen(y)); 737 // expected-warning@-1 {{String concatenation function overflows the destination buffer}} 738 } 739 740 void strncat_overflow_2(char *y) { 741 char x[4] = "12"; 742 if (strlen(y) == 2) 743 strncat(x, y, strlen(y)); 744 // expected-warning@-1 {{String concatenation function overflows the destination buffer}} 745 } 746 747 void strncat_overflow_3(char *y) { 748 char x[4] = "12"; 749 if (strlen(y) == 4) 750 strncat(x, y, 2); 751 // expected-warning@-1 {{String concatenation function overflows the destination buffer}} 752 } 753 #endif 754 755 void strncat_no_overflow_1(char *y) { 756 char x[5] = "12"; 757 if (strlen(y) == 2) 758 strncat(x, y, strlen(y)); // no-warning 759 } 760 761 void strncat_no_overflow_2(char *y) { 762 char x[4] = "12"; 763 if (strlen(y) == 4) 764 strncat(x, y, 1); // no-warning 765 } 766 767 void strncat_symbolic_dst_length(char *dst) { 768 strncat(dst, "1234", 5); 769 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 770 } 771 772 #ifndef SUPPRESS_OUT_OF_BOUND 773 void strncat_symbolic_src_length(char *src) { 774 char dst[8] = "1234"; 775 strncat(dst, src, 3); 776 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 777 778 char dst2[8] = "1234"; 779 strncat(dst2, src, 4); 780 // expected-warning@-1 {{String concatenation function overflows the destination buffer}} 781 } 782 783 void strncat_unknown_src_length(char *src, int offset) { 784 char dst[8] = "1234"; 785 strncat(dst, &src[offset], 3); 786 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 787 788 char dst2[8] = "1234"; 789 strncat(dst2, &src[offset], 4); 790 // expected-warning@-1 {{String concatenation function overflows the destination buffer}} 791 } 792 #endif 793 794 // There is no strncat_unknown_dst_length because if we can't get a symbolic 795 // length for the "before" strlen, we won't be able to set one for "after". 796 797 void strncat_symbolic_limit(unsigned limit) { 798 char dst[6] = "1234"; 799 char src[] = "567"; 800 strncat(dst, src, limit); // no-warning 801 802 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 803 clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}} 804 } 805 806 void strncat_unknown_limit(float limit) { 807 char dst[6] = "1234"; 808 char src[] = "567"; 809 strncat(dst, src, (size_t)limit); // no-warning 810 811 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}} 812 clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}} 813 } 814 815 void strncat_too_big(char *dst, char *src) { 816 // We assume this will never actually happen, so we don't get a warning. 817 if (strlen(dst) != (((size_t)0) - 2)) 818 return; 819 if (strlen(src) != 2) 820 return; 821 strncat(dst, src, 2); 822 } 823 824 void strncat_zero(char *src) { 825 char dst[] = "123"; 826 strncat(dst, src, 0); // no-warning 827 } 828 829 void strncat_empty(void) { 830 char dst[8] = "123"; 831 char src[] = ""; 832 strncat(dst, src, 4); // no-warning 833 } 834 835 //===----------------------------------------------------------------------=== 836 // strcmp() 837 //===----------------------------------------------------------------------=== 838 839 #define strcmp BUILTIN(strcmp) 840 int strcmp(const char * s1, const char * s2); 841 842 void strcmp_check_modelling(void) { 843 char *x = "aa"; 844 char *y = "a"; 845 clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}} 846 clang_analyzer_eval(strcmp(x, y) <= 0); // expected-warning{{FALSE}} 847 clang_analyzer_eval(strcmp(x, y) > 1); // expected-warning{{UNKNOWN}} 848 849 clang_analyzer_eval(strcmp(y, x) < 0); // expected-warning{{TRUE}} 850 clang_analyzer_eval(strcmp(y, x) >= 0); // expected-warning{{FALSE}} 851 clang_analyzer_eval(strcmp(y, x) < -1); // expected-warning{{UNKNOWN}} 852 } 853 854 void strcmp_constant0(void) { 855 clang_analyzer_eval(strcmp("123", "123") == 0); // expected-warning{{TRUE}} 856 } 857 858 void strcmp_constant_and_var_0(void) { 859 char *x = "123"; 860 clang_analyzer_eval(strcmp(x, "123") == 0); // expected-warning{{TRUE}} 861 } 862 863 void strcmp_constant_and_var_1(void) { 864 char *x = "123"; 865 clang_analyzer_eval(strcmp("123", x) == 0); // expected-warning{{TRUE}} 866 } 867 868 void strcmp_0(void) { 869 char *x = "123"; 870 char *y = "123"; 871 clang_analyzer_eval(strcmp(x, y) == 0); // expected-warning{{TRUE}} 872 } 873 874 void strcmp_1(void) { 875 char *x = "234"; 876 char *y = "123"; 877 clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}} 878 } 879 880 void strcmp_2(void) { 881 char *x = "123"; 882 char *y = "234"; 883 clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}} 884 } 885 886 void strcmp_null_0(void) { 887 char *x = NULL; 888 char *y = "123"; 889 strcmp(x, y); // expected-warning{{Null pointer passed as 1st argument to string comparison function}} 890 } 891 892 void strcmp_null_1(void) { 893 char *x = "123"; 894 char *y = NULL; 895 strcmp(x, y); // expected-warning{{Null pointer passed as 2nd argument to string comparison function}} 896 } 897 898 void strcmp_diff_length_0(void) { 899 char *x = "12345"; 900 char *y = "234"; 901 clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}} 902 } 903 904 void strcmp_diff_length_1(void) { 905 char *x = "123"; 906 char *y = "23456"; 907 clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}} 908 } 909 910 void strcmp_diff_length_2(void) { 911 char *x = "12345"; 912 char *y = "123"; 913 clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}} 914 } 915 916 void strcmp_diff_length_3(void) { 917 char *x = "123"; 918 char *y = "12345"; 919 clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}} 920 } 921 922 void strcmp_embedded_null (void) { 923 clang_analyzer_eval(strcmp("\0z", "\0y") == 0); // expected-warning{{TRUE}} 924 } 925 926 void strcmp_unknown_arg (char *unknown) { 927 clang_analyzer_eval(strcmp(unknown, unknown) == 0); // expected-warning{{TRUE}} 928 } 929 930 union argument { 931 char *f; 932 }; 933 934 void function_pointer_cast_helper(char **a) { 935 strcmp("Hi", *a); // PR24951 crash 936 } 937 938 void strcmp_union_function_pointer_cast(union argument a) { 939 void (*fPtr)(union argument *) = (void (*)(union argument *))function_pointer_cast_helper; 940 941 fPtr(&a); 942 } 943 944 int strcmp_null_argument(char *a) { 945 char *b = 0; 946 // Do not warn about the first argument! 947 return strcmp(a, b); // expected-warning{{Null pointer passed as 2nd argument to string comparison function}} 948 } 949 950 void strcmp_fn_r(char *x) { 951 strcmp(x, (char*)&strcmp_null_argument); // expected-warning{{Argument to string comparison function is the address of the function 'strcmp_null_argument', which is not a null-terminated string}} 952 } 953 954 void strcmp_fn_l(char *x) { 955 strcmp((char*)&strcmp_null_argument, x); // expected-warning{{Argument to string comparison function is the address of the function 'strcmp_null_argument', which is not a null-terminated string}} 956 } 957 958 //===----------------------------------------------------------------------=== 959 // strncmp() 960 //===----------------------------------------------------------------------=== 961 962 #define strncmp BUILTIN(strncmp) 963 int strncmp(const char *s1, const char *s2, size_t n); 964 965 void strncmp_check_modelling(void) { 966 char *x = "aa"; 967 char *y = "a"; 968 clang_analyzer_eval(strncmp(x, y, 2) > 0); // expected-warning{{TRUE}} 969 clang_analyzer_eval(strncmp(x, y, 2) <= 0); // expected-warning{{FALSE}} 970 clang_analyzer_eval(strncmp(x, y, 2) > 1); // expected-warning{{UNKNOWN}} 971 972 clang_analyzer_eval(strncmp(y, x, 2) < 0); // expected-warning{{TRUE}} 973 clang_analyzer_eval(strncmp(y, x, 2) >= 0); // expected-warning{{FALSE}} 974 clang_analyzer_eval(strncmp(y, x, 2) < -1); // expected-warning{{UNKNOWN}} 975 } 976 977 void strncmp_constant0(void) { 978 clang_analyzer_eval(strncmp("123", "123", 3) == 0); // expected-warning{{TRUE}} 979 } 980 981 void strncmp_constant_and_var_0(void) { 982 char *x = "123"; 983 clang_analyzer_eval(strncmp(x, "123", 3) == 0); // expected-warning{{TRUE}} 984 } 985 986 void strncmp_constant_and_var_1(void) { 987 char *x = "123"; 988 clang_analyzer_eval(strncmp("123", x, 3) == 0); // expected-warning{{TRUE}} 989 } 990 991 void strncmp_0(void) { 992 char *x = "123"; 993 char *y = "123"; 994 clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}} 995 } 996 997 void strncmp_1(void) { 998 char *x = "234"; 999 char *y = "123"; 1000 clang_analyzer_eval(strncmp(x, y, 3) > 0); // expected-warning{{TRUE}} 1001 } 1002 1003 void strncmp_2(void) { 1004 char *x = "123"; 1005 char *y = "234"; 1006 clang_analyzer_eval(strncmp(x, y, 3) < 0); // expected-warning{{TRUE}} 1007 } 1008 1009 void strncmp_null_0(void) { 1010 char *x = NULL; 1011 char *y = "123"; 1012 strncmp(x, y, 3); // expected-warning{{Null pointer passed as 1st argument to string comparison function}} 1013 } 1014 1015 void strncmp_null_1(void) { 1016 char *x = "123"; 1017 char *y = NULL; 1018 strncmp(x, y, 3); // expected-warning{{Null pointer passed as 2nd argument to string comparison function}} 1019 } 1020 1021 void strncmp_diff_length_0(void) { 1022 char *x = "12345"; 1023 char *y = "234"; 1024 clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}} 1025 } 1026 1027 void strncmp_diff_length_1(void) { 1028 char *x = "123"; 1029 char *y = "23456"; 1030 clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}} 1031 } 1032 1033 void strncmp_diff_length_2(void) { 1034 char *x = "12345"; 1035 char *y = "123"; 1036 clang_analyzer_eval(strncmp(x, y, 5) > 0); // expected-warning{{TRUE}} 1037 } 1038 1039 void strncmp_diff_length_3(void) { 1040 char *x = "123"; 1041 char *y = "12345"; 1042 clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}} 1043 } 1044 1045 void strncmp_diff_length_4(void) { 1046 char *x = "123"; 1047 char *y = "12345"; 1048 clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}} 1049 } 1050 1051 void strncmp_diff_length_5(void) { 1052 char *x = "012"; 1053 char *y = "12345"; 1054 clang_analyzer_eval(strncmp(x, y, 3) < 0); // expected-warning{{TRUE}} 1055 } 1056 1057 void strncmp_diff_length_6(void) { 1058 char *x = "234"; 1059 char *y = "12345"; 1060 clang_analyzer_eval(strncmp(x, y, 3) > 0); // expected-warning{{TRUE}} 1061 } 1062 1063 void strncmp_embedded_null (void) { 1064 clang_analyzer_eval(strncmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}} 1065 } 1066 1067 int strncmp_null_argument(char *a, size_t n) { 1068 char *b = 0; 1069 // Do not warn about the first argument! 1070 return strncmp(a, b, n); // expected-warning{{Null pointer passed as 2nd argument to string comparison function}} 1071 } 1072 1073 //===----------------------------------------------------------------------=== 1074 // strcasecmp() 1075 //===----------------------------------------------------------------------=== 1076 1077 #define strcasecmp BUILTIN(strcasecmp) 1078 int strcasecmp(const char *s1, const char *s2); 1079 1080 void strcasecmp_check_modelling(void) { 1081 char *x = "aa"; 1082 char *y = "a"; 1083 clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}} 1084 clang_analyzer_eval(strcasecmp(x, y) <= 0); // expected-warning{{FALSE}} 1085 clang_analyzer_eval(strcasecmp(x, y) > 1); // expected-warning{{UNKNOWN}} 1086 1087 clang_analyzer_eval(strcasecmp(y, x) < 0); // expected-warning{{TRUE}} 1088 clang_analyzer_eval(strcasecmp(y, x) >= 0); // expected-warning{{FALSE}} 1089 clang_analyzer_eval(strcasecmp(y, x) < -1); // expected-warning{{UNKNOWN}} 1090 } 1091 1092 void strcasecmp_constant0(void) { 1093 clang_analyzer_eval(strcasecmp("abc", "Abc") == 0); // expected-warning{{TRUE}} 1094 } 1095 1096 void strcasecmp_constant_and_var_0(void) { 1097 char *x = "abc"; 1098 clang_analyzer_eval(strcasecmp(x, "Abc") == 0); // expected-warning{{TRUE}} 1099 } 1100 1101 void strcasecmp_constant_and_var_1(void) { 1102 char *x = "abc"; 1103 clang_analyzer_eval(strcasecmp("Abc", x) == 0); // expected-warning{{TRUE}} 1104 } 1105 1106 void strcasecmp_0(void) { 1107 char *x = "abc"; 1108 char *y = "Abc"; 1109 clang_analyzer_eval(strcasecmp(x, y) == 0); // expected-warning{{TRUE}} 1110 } 1111 1112 void strcasecmp_1(void) { 1113 char *x = "Bcd"; 1114 char *y = "abc"; 1115 clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}} 1116 } 1117 1118 void strcasecmp_2(void) { 1119 char *x = "abc"; 1120 char *y = "Bcd"; 1121 clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}} 1122 } 1123 1124 void strcasecmp_null_0(void) { 1125 char *x = NULL; 1126 char *y = "123"; 1127 strcasecmp(x, y); // expected-warning{{Null pointer passed as 1st argument to string comparison function}} 1128 } 1129 1130 void strcasecmp_null_1(void) { 1131 char *x = "123"; 1132 char *y = NULL; 1133 strcasecmp(x, y); // expected-warning{{Null pointer passed as 2nd argument to string comparison function}} 1134 } 1135 1136 void strcasecmp_diff_length_0(void) { 1137 char *x = "abcde"; 1138 char *y = "aBd"; 1139 clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}} 1140 } 1141 1142 void strcasecmp_diff_length_1(void) { 1143 char *x = "abc"; 1144 char *y = "aBdef"; 1145 clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}} 1146 } 1147 1148 void strcasecmp_diff_length_2(void) { 1149 char *x = "aBcDe"; 1150 char *y = "abc"; 1151 clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}} 1152 } 1153 1154 void strcasecmp_diff_length_3(void) { 1155 char *x = "aBc"; 1156 char *y = "abcde"; 1157 clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}} 1158 } 1159 1160 void strcasecmp_embedded_null (void) { 1161 clang_analyzer_eval(strcasecmp("ab\0zz", "ab\0yy") == 0); // expected-warning{{TRUE}} 1162 } 1163 1164 int strcasecmp_null_argument(char *a) { 1165 char *b = 0; 1166 // Do not warn about the first argument! 1167 return strcasecmp(a, b); // expected-warning{{Null pointer passed as 2nd argument to string comparison function}} 1168 } 1169 1170 //===----------------------------------------------------------------------=== 1171 // strncasecmp() 1172 //===----------------------------------------------------------------------=== 1173 1174 #define strncasecmp BUILTIN(strncasecmp) 1175 int strncasecmp(const char *s1, const char *s2, size_t n); 1176 1177 void strncasecmp_check_modelling(void) { 1178 char *x = "aa"; 1179 char *y = "a"; 1180 clang_analyzer_eval(strncasecmp(x, y, 2) > 0); // expected-warning{{TRUE}} 1181 clang_analyzer_eval(strncasecmp(x, y, 2) <= 0); // expected-warning{{FALSE}} 1182 clang_analyzer_eval(strncasecmp(x, y, 2) > 1); // expected-warning{{UNKNOWN}} 1183 1184 clang_analyzer_eval(strncasecmp(y, x, 2) < 0); // expected-warning{{TRUE}} 1185 clang_analyzer_eval(strncasecmp(y, x, 2) >= 0); // expected-warning{{FALSE}} 1186 clang_analyzer_eval(strncasecmp(y, x, 2) < -1); // expected-warning{{UNKNOWN}} 1187 } 1188 1189 void strncasecmp_constant0(void) { 1190 clang_analyzer_eval(strncasecmp("abc", "Abc", 3) == 0); // expected-warning{{TRUE}} 1191 } 1192 1193 void strncasecmp_constant_and_var_0(void) { 1194 char *x = "abc"; 1195 clang_analyzer_eval(strncasecmp(x, "Abc", 3) == 0); // expected-warning{{TRUE}} 1196 } 1197 1198 void strncasecmp_constant_and_var_1(void) { 1199 char *x = "abc"; 1200 clang_analyzer_eval(strncasecmp("Abc", x, 3) == 0); // expected-warning{{TRUE}} 1201 } 1202 1203 void strncasecmp_0(void) { 1204 char *x = "abc"; 1205 char *y = "Abc"; 1206 clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}} 1207 } 1208 1209 void strncasecmp_1(void) { 1210 char *x = "Bcd"; 1211 char *y = "abc"; 1212 clang_analyzer_eval(strncasecmp(x, y, 3) > 0); // expected-warning{{TRUE}} 1213 } 1214 1215 void strncasecmp_2(void) { 1216 char *x = "abc"; 1217 char *y = "Bcd"; 1218 clang_analyzer_eval(strncasecmp(x, y, 3) < 0); // expected-warning{{TRUE}} 1219 } 1220 1221 void strncasecmp_null_0(void) { 1222 char *x = NULL; 1223 char *y = "123"; 1224 strncasecmp(x, y, 3); // expected-warning{{Null pointer passed as 1st argument to string comparison function}} 1225 } 1226 1227 void strncasecmp_null_1(void) { 1228 char *x = "123"; 1229 char *y = NULL; 1230 strncasecmp(x, y, 3); // expected-warning{{Null pointer passed as 2nd argument to string comparison function}} 1231 } 1232 1233 void strncasecmp_diff_length_0(void) { 1234 char *x = "abcde"; 1235 char *y = "aBd"; 1236 clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}} 1237 } 1238 1239 void strncasecmp_diff_length_1(void) { 1240 char *x = "abc"; 1241 char *y = "aBdef"; 1242 clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}} 1243 } 1244 1245 void strncasecmp_diff_length_2(void) { 1246 char *x = "aBcDe"; 1247 char *y = "abc"; 1248 clang_analyzer_eval(strncasecmp(x, y, 5) > 0); // expected-warning{{TRUE}} 1249 } 1250 1251 void strncasecmp_diff_length_3(void) { 1252 char *x = "aBc"; 1253 char *y = "abcde"; 1254 clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}} 1255 } 1256 1257 void strncasecmp_diff_length_4(void) { 1258 char *x = "abcde"; 1259 char *y = "aBc"; 1260 clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}} 1261 } 1262 1263 void strncasecmp_diff_length_5(void) { 1264 char *x = "abcde"; 1265 char *y = "aBd"; 1266 clang_analyzer_eval(strncasecmp(x, y, 3) < 0); // expected-warning{{TRUE}} 1267 } 1268 1269 void strncasecmp_diff_length_6(void) { 1270 char *x = "aBDe"; 1271 char *y = "abc"; 1272 clang_analyzer_eval(strncasecmp(x, y, 3) > 0); // expected-warning{{TRUE}} 1273 } 1274 1275 void strncasecmp_embedded_null (void) { 1276 clang_analyzer_eval(strncasecmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}} 1277 } 1278 1279 int strncasecmp_null_argument(char *a, size_t n) { 1280 char *b = 0; 1281 // Do not warn about the first argument! 1282 return strncasecmp(a, b, n); // expected-warning{{Null pointer passed as 2nd argument to string comparison function}} 1283 } 1284 1285 //===----------------------------------------------------------------------=== 1286 // strsep() 1287 //===----------------------------------------------------------------------=== 1288 1289 char *strsep(char ** restrict stringp, const char * restrict delim); 1290 1291 void strsep_null_delim(char *s) { 1292 strsep(&s, NULL); // expected-warning{{Null pointer passed as 2nd argument to strsep()}} 1293 } 1294 1295 void strsep_null_search(void) { 1296 strsep(NULL, ""); // expected-warning{{Null pointer passed as 1st argument to strsep()}} 1297 } 1298 1299 void strsep_return_original_pointer(char *s) { 1300 char *original = s; 1301 char *result = strsep(&s, ""); // no-warning 1302 clang_analyzer_eval(original == result); // expected-warning{{TRUE}} 1303 } 1304 1305 void strsep_null_string(void) { 1306 char *s = NULL; 1307 char *result = strsep(&s, ""); // no-warning 1308 clang_analyzer_eval(result == NULL); // expected-warning{{TRUE}} 1309 } 1310 1311 void strsep_changes_input_pointer(char *s) { 1312 char *original = s; 1313 strsep(&s, ""); // no-warning 1314 clang_analyzer_eval(s == original); // expected-warning{{UNKNOWN}} 1315 clang_analyzer_eval(s == NULL); // expected-warning{{UNKNOWN}} 1316 1317 // Check that the value is symbolic. 1318 if (s == NULL) { 1319 clang_analyzer_eval(s == NULL); // expected-warning{{TRUE}} 1320 } 1321 } 1322 1323 void strsep_changes_input_string(void) { 1324 char str[] = "abc"; 1325 1326 clang_analyzer_eval(str[1] == 'b'); // expected-warning{{TRUE}} 1327 1328 char *s = str; 1329 strsep(&s, "b"); // no-warning 1330 1331 // The real strsep will change the first delimiter it finds into a NUL 1332 // character. For now, we just model the invalidation. 1333 clang_analyzer_eval(str[1] == 'b'); // expected-warning{{UNKNOWN}} 1334 } 1335 1336 //===----------------------------------------------------------------------=== 1337 // memset() / explicit_bzero() / bzero() 1338 //===----------------------------------------------------------------------=== 1339 1340 void *memset(void *dest, int ch, size_t count); 1341 1342 void bzero(void *dst, size_t count); 1343 void explicit_bzero(void *dest, size_t count); 1344 1345 void *malloc(size_t size); 1346 void free(void *); 1347 1348 void memset1_char_array_null(void) { 1349 char str[] = "abcd"; 1350 clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}} 1351 memset(str, '\0', 2); 1352 clang_analyzer_eval(strlen(str) == 0); // expected-warning{{TRUE}} 1353 } 1354 1355 void memset2_char_array_null(void) { 1356 char str[] = "abcd"; 1357 clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}} 1358 memset(str, '\0', strlen(str) + 1); 1359 clang_analyzer_eval(strlen(str) == 0); // expected-warning{{TRUE}} 1360 clang_analyzer_eval(str[2] == 0); // expected-warning{{TRUE}} 1361 } 1362 1363 void memset3_char_malloc_null(void) { 1364 char *str = (char *)malloc(10 * sizeof(char)); 1365 memset(str + 1, '\0', 8); 1366 clang_analyzer_eval(str[1] == 0); // expected-warning{{UNKNOWN}} 1367 free(str); 1368 } 1369 1370 void memset4_char_malloc_null(void) { 1371 char *str = (char *)malloc(10 * sizeof(char)); 1372 //void *str = malloc(10 * sizeof(char)); 1373 memset(str, '\0', 10); 1374 clang_analyzer_eval(str[1] == 0); // expected-warning{{TRUE}} 1375 clang_analyzer_eval(strlen(str) == 0); // expected-warning{{TRUE}} 1376 free(str); 1377 } 1378 1379 #ifdef SUPPRESS_OUT_OF_BOUND 1380 void memset5_char_malloc_overflow_null(void) { 1381 char *str = (char *)malloc(10 * sizeof(char)); 1382 memset(str, '\0', 12); 1383 clang_analyzer_eval(str[1] == 0); // expected-warning{{UNKNOWN}} 1384 free(str); 1385 } 1386 #endif 1387 1388 void memset6_char_array_nonnull(void) { 1389 char str[] = "abcd"; 1390 clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}} 1391 memset(str, '0', 2); 1392 clang_analyzer_eval(str[0] == 'a'); // expected-warning{{UNKNOWN}} 1393 clang_analyzer_eval(strlen(str) == 4); // expected-warning{{UNKNOWN}} 1394 } 1395 1396 #ifdef SUPPRESS_OUT_OF_BOUND 1397 void memset8_char_array_nonnull(void) { 1398 char str[5] = "abcd"; 1399 clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}} 1400 memset(str, '0', 10); // expected-warning{{'memset' will always overflow; destination buffer has size 5, but size argument is 10}} 1401 clang_analyzer_eval(str[0] != '0'); // expected-warning{{UNKNOWN}} 1402 clang_analyzer_eval(strlen(str) >= 10); // expected-warning{{TRUE}} 1403 clang_analyzer_eval(strlen(str) < 10); // expected-warning{{FALSE}} 1404 } 1405 #endif 1406 1407 struct POD_memset { 1408 int num; 1409 char c; 1410 }; 1411 1412 void memset10_struct(void) { 1413 struct POD_memset pod; 1414 char *str = (char *)&pod; 1415 pod.num = 1; 1416 pod.c = 1; 1417 clang_analyzer_eval(pod.num == 0); // expected-warning{{FALSE}} 1418 memset(str, 0, sizeof(struct POD_memset)); 1419 clang_analyzer_eval(pod.num == 0); // expected-warning{{TRUE}} 1420 } 1421 1422 #ifdef SUPPRESS_OUT_OF_BOUND 1423 void memset11_struct_field(void) { 1424 struct POD_memset pod; 1425 pod.num = 1; 1426 pod.c = '1'; 1427 memset(&pod.num, 0, sizeof(struct POD_memset)); 1428 1429 clang_analyzer_eval(pod.num == 0); // expected-warning{{TRUE}} 1430 clang_analyzer_eval(pod.c == '\0'); // expected-warning{{TRUE}} 1431 } 1432 1433 void memset12_struct_field(void) { 1434 struct POD_memset pod; 1435 pod.num = 1; 1436 pod.c = '1'; 1437 memset(&pod.c, 0, sizeof(struct POD_memset)); // expected-warning {{'memset' will always overflow; destination buffer has size 4, but size argument is 8}} 1438 clang_analyzer_eval(pod.num == 0); // expected-warning{{UNKNOWN}} 1439 clang_analyzer_eval(pod.c == 0); // expected-warning{{UNKNOWN}} 1440 } 1441 1442 union U_memset { 1443 int i; 1444 double d; 1445 char c; 1446 }; 1447 1448 void memset13_union_field(void) { 1449 union U_memset u; 1450 u.i = 5; 1451 memset(&u.i, '\0', sizeof(union U_memset)); 1452 // Note: This should be TRUE, analyzer can't handle union perfectly now. 1453 clang_analyzer_eval(u.d == 0); // expected-warning{{UNKNOWN}} 1454 } 1455 #endif 1456 1457 void memset14_region_cast(void) { 1458 char *str = (char *)malloc(10 * sizeof(int)); 1459 int *array = (int *)str; 1460 memset(array, 0, 10 * sizeof(int)); 1461 clang_analyzer_eval(str[10] == '\0'); // expected-warning{{TRUE}} 1462 clang_analyzer_eval(strlen((char *)array) == 0); // expected-warning{{TRUE}} 1463 clang_analyzer_eval(strlen(str) == 0); // expected-warning{{TRUE}} 1464 free(str); 1465 } 1466 1467 void memset15_region_cast(void) { 1468 char *str = (char *)malloc(10 * sizeof(int)); 1469 int *array = (int *)str; 1470 memset(array, 0, 5 * sizeof(int)); 1471 clang_analyzer_eval(str[10] == '\0'); // expected-warning{{UNKNOWN}} 1472 clang_analyzer_eval(strlen((char *)array) == 0); // expected-warning{{TRUE}} 1473 clang_analyzer_eval(strlen(str) == 0); // expected-warning{{TRUE}} 1474 free(str); 1475 } 1476 1477 int memset20_scalar(void) { 1478 int *x = malloc(sizeof(int)); 1479 *x = 10; 1480 memset(x, 0, sizeof(int)); 1481 int num = 1 / *x; // expected-warning{{Division by zero}} 1482 free(x); 1483 return num; 1484 } 1485 1486 int memset21_scalar(void) { 1487 int *x = malloc(sizeof(int)); 1488 memset(x, 0, 1); 1489 int num = 1 / *x; 1490 free(x); 1491 return num; 1492 } 1493 1494 void memset22_array(void) { 1495 int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; 1496 clang_analyzer_eval(array[1] == 2); // expected-warning{{TRUE}} 1497 memset(array, 0, sizeof(array)); 1498 clang_analyzer_eval(array[1] == 0); // expected-warning{{TRUE}} 1499 } 1500 1501 void memset23_array_pod_object(void) { 1502 struct POD_memset array[10]; 1503 array[1].num = 10; 1504 array[1].c = 'c'; 1505 clang_analyzer_eval(array[1].num == 10); // expected-warning{{TRUE}} 1506 memset(&array[1], 0, sizeof(struct POD_memset)); 1507 clang_analyzer_eval(array[1].num == 0); // expected-warning{{UNKNOWN}} 1508 } 1509 1510 void memset24_array_pod_object(void) { 1511 struct POD_memset array[10]; 1512 array[1].num = 10; 1513 array[1].c = 'c'; 1514 clang_analyzer_eval(array[1].num == 10); // expected-warning{{TRUE}} 1515 memset(array, 0, sizeof(array)); 1516 clang_analyzer_eval(array[1].num == 0); // expected-warning{{TRUE}} 1517 } 1518 1519 void memset25_symbol(char c) { 1520 char array[10] = {1}; 1521 if (c != 0) 1522 return; 1523 1524 memset(array, c, 10); 1525 1526 clang_analyzer_eval(strlen(array) == 0); // expected-warning{{TRUE}} 1527 clang_analyzer_eval(array[4] == 0); // expected-warning{{TRUE}} 1528 } 1529 1530 void memset26_upper_UCHAR_MAX(void) { 1531 char array[10] = {1}; 1532 1533 memset(array, 1024, 10); 1534 1535 clang_analyzer_eval(strlen(array) == 0); // expected-warning{{TRUE}} 1536 clang_analyzer_eval(array[4] == 0); // expected-warning{{TRUE}} 1537 } 1538 1539 void bzero1_null(void) { 1540 char *a = NULL; 1541 1542 bzero(a, 10); // expected-warning{{Null pointer passed as 1st argument to memory clearance function}} 1543 } 1544 1545 void bzero2_char_array_null(void) { 1546 char str[] = "abcd"; 1547 clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}} 1548 bzero(str, 2); 1549 clang_analyzer_eval(strlen(str) == 0); // expected-warning{{TRUE}} 1550 } 1551 1552 void bzero3_char_ptr_null(void) { 1553 char *str = "abcd"; 1554 clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}} 1555 bzero(str + 2, 2); 1556 clang_analyzer_eval(strlen(str) == 0); // expected-warning{{FALSE}} 1557 } 1558 1559 void explicit_bzero1_null(void) { 1560 char *a = NULL; 1561 1562 explicit_bzero(a, 10); // expected-warning{{Null pointer passed as 1st argument to memory clearance function}} 1563 } 1564 1565 void explicit_bzero2_clear_mypassword(void) { 1566 char passwd[7] = "passwd"; 1567 1568 explicit_bzero(passwd, sizeof(passwd)); // no-warning 1569 1570 clang_analyzer_eval(strlen(passwd) == 0); // expected-warning{{TRUE}} 1571 clang_analyzer_eval(passwd[0] == '\0'); // expected-warning{{TRUE}} 1572 } 1573 1574 void explicit_bzero3_out_ofbound(void) { 1575 char *privkey = (char *)malloc(7); 1576 const char newprivkey[10] = "mysafekey"; 1577 1578 strcpy(privkey, "random"); 1579 explicit_bzero(privkey, sizeof(newprivkey)); 1580 #ifndef SUPPRESS_OUT_OF_BOUND 1581 // expected-warning@-2 {{Memory clearance function overflows the destination buffer}} 1582 #endif 1583 clang_analyzer_eval(privkey[0] == '\0'); 1584 #ifdef SUPPRESS_OUT_OF_BOUND 1585 // expected-warning@-2 {{UNKNOWN}} 1586 #endif 1587 free(privkey); 1588 } 1589 1590 //===----------------------------------------------------------------------=== 1591 // FIXMEs 1592 //===----------------------------------------------------------------------=== 1593 1594 // The analyzer_eval call below should evaluate to true. We are being too 1595 // aggressive in marking the (length of) src symbol dead. The length of dst 1596 // depends on src. This could be explicitly specified in the checker or the 1597 // logic for handling MetadataSymbol in SymbolManager needs to change. 1598 void strcat_symbolic_src_length(char *src) { 1599 char dst[8] = "1234"; 1600 strcat(dst, src); 1601 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{UNKNOWN}} 1602 } 1603 1604 1605 // The analyzer_eval call below should evaluate to true. Most likely the same 1606 // issue as the test above. 1607 void strncpy_exactly_matching_buffer2(char *y) { 1608 if (strlen(y) >= 4) 1609 return; 1610 1611 char x[4]; 1612 strncpy(x, y, 4); // no-warning 1613 1614 // This time, we know that y fits in x anyway. 1615 clang_analyzer_eval(strlen(x) <= 3); // expected-warning{{UNKNOWN}} 1616 } 1617 1618 void memset7_char_array_nonnull(void) { 1619 char str[5] = "abcd"; 1620 clang_analyzer_eval(strlen(str) == 4); // expected-warning{{TRUE}} 1621 memset(str, '0', 5); 1622 // FIXME: This should be TRUE. 1623 clang_analyzer_eval(str[0] == '0'); // expected-warning{{UNKNOWN}} 1624 clang_analyzer_eval(strlen(str) >= 5); // expected-warning{{TRUE}} 1625 } 1626 1627 void memset16_region_cast(void) { 1628 char *str = (char *)malloc(10 * sizeof(int)); 1629 int *array = (int *)str; 1630 memset(array, '0', 10 * sizeof(int)); 1631 // FIXME: This should be TRUE. 1632 clang_analyzer_eval(str[10] == '0'); // expected-warning{{UNKNOWN}} 1633 clang_analyzer_eval(strlen((char *)array) >= 10 * sizeof(int)); // expected-warning{{TRUE}} 1634 clang_analyzer_eval(strlen(str) >= 10 * sizeof(int)); // expected-warning{{TRUE}} 1635 free(str); 1636 } 1637 1638 #ifdef SUPPRESS_OUT_OF_BOUND 1639 void memset17_region_cast(void) { 1640 char *str = (char *)malloc(10 * sizeof(int)); 1641 int *array = (int *)str; 1642 memset(array, '0', 12 * sizeof(int)); 1643 clang_analyzer_eval(str[10] == '0'); // expected-warning{{UNKNOWN}} 1644 clang_analyzer_eval(strlen((char *)array) >= 12 * sizeof(int)); // expected-warning{{TRUE}} 1645 clang_analyzer_eval(strlen(str) >= 12 * sizeof(int)); // expected-warning{{TRUE}} 1646 free(str); 1647 } 1648 1649 void memset18_memset_multiple_times(void) { 1650 char *str = (char *)malloc(10 * sizeof(char)); 1651 clang_analyzer_eval(strlen(str) == 0); // expected-warning{{UNKNOWN}} 1652 1653 memset(str + 2, '\0', 10 * sizeof(char)); 1654 clang_analyzer_eval(strlen(str) == 0); // expected-warning{{UNKNOWN}} 1655 clang_analyzer_eval(str[1] == '\0'); // expected-warning{{UNKNOWN}} 1656 1657 memset(str, '0', 10 * sizeof(char)); 1658 clang_analyzer_eval(strlen(str) >= 10); // expected-warning{{TRUE}} 1659 // FIXME: This should be TRUE. 1660 clang_analyzer_eval(str[1] == '0'); // expected-warning{{UNKNOWN}} 1661 1662 free(str); 1663 } 1664 1665 void memset19_memset_multiple_times(void) { 1666 char *str = (char *)malloc(10 * sizeof(char)); 1667 clang_analyzer_eval(strlen(str) == 0); // expected-warning{{UNKNOWN}} 1668 1669 memset(str, '0', 10 * sizeof(char)); 1670 clang_analyzer_eval(strlen(str) >= 10); // expected-warning{{TRUE}} 1671 // FIXME: This should be TRUE. 1672 clang_analyzer_eval(str[1] == '0'); // expected-warning{{UNKNOWN}} 1673 1674 memset(str + 2, '\0', 10 * sizeof(char)); 1675 clang_analyzer_eval(strlen(str) >= 10); // expected-warning{{UNKNOWN}} 1676 clang_analyzer_eval(str[1] == '0'); // expected-warning{{UNKNOWN}} 1677 1678 free(str); 1679 } 1680 #endif 1681 1682 // The analyzer does not support binding a symbol with default binding. 1683 void memset27_symbol(char c) { 1684 char array[10] = {0}; 1685 if (c < 10) 1686 return; 1687 1688 memset(array, c, 10); 1689 1690 clang_analyzer_eval(strlen(array) >= 10); // expected-warning{{TRUE}} 1691 // FIXME: This should be TRUE. 1692 clang_analyzer_eval(array[4] >= 10); // expected-warning{{UNKNOWN}} 1693 } 1694 1695 void memset28(void) { 1696 short x; 1697 memset(&x, 1, sizeof(short)); 1698 // This should be true. 1699 clang_analyzer_eval(x == 0x101); // expected-warning{{UNKNOWN}} 1700 } 1701 1702 void memset29_plain_int_zero(void) { 1703 short x; 1704 memset(&x, 0, sizeof(short)); 1705 clang_analyzer_eval(x == 0); // expected-warning{{TRUE}} 1706 } 1707 1708 void test_memset_chk(void) { 1709 int x; 1710 __builtin___memset_chk(&x, 0, sizeof(x), __builtin_object_size(&x, 0)); 1711 clang_analyzer_eval(x == 0); // expected-warning{{TRUE}} 1712 } 1713 1714 #ifndef SUPPRESS_OUT_OF_BOUND 1715 void strcpy_no_overflow_2(char *y) { 1716 char x[3]; 1717 // FIXME: string literal modeling does not account for embedded NULLs. 1718 // This case should not elicit a warning, but does. 1719 // See discussion at https://reviews.llvm.org/D129269 1720 strcpy(x, "12\0"); // expected-warning{{String copy function overflows the destination buffer}} 1721 } 1722 #else 1723 void strcpy_no_overflow_2(char *y) { 1724 char x[3]; 1725 strcpy(x, "12\0"); 1726 } 1727 #endif 1728 1729 #ifndef SUPPRESS_OUT_OF_BOUND 1730 void testStrcpyDestinationWritableFirstByte(void) { 1731 char dst[10]; 1732 char *p = dst - 8; 1733 strcpy(p, "src"); // expected-warning {{String copy function overflows the destination buffer}} 1734 } 1735 1736 void CWE124_Buffer_Underwrite__malloc_char_cpy() { 1737 char * dataBuffer = (char *)malloc(100*sizeof(char)); 1738 if (dataBuffer == NULL) return; 1739 memset(dataBuffer, 'A', 100-1); 1740 dataBuffer[100-1] = '\0'; 1741 char * data = dataBuffer - 8; 1742 char source[100]; 1743 memset(source, 'C', 100-1); // fill with 'C's 1744 source[100-1] = '\0'; // null terminate 1745 strcpy(data, source); // expected-warning {{String copy function overflows the destination buffer}} 1746 free(dataBuffer); 1747 } 1748 #endif 1749 1750 #ifndef SUPPRESS_OUT_OF_BOUND 1751 void testStrncpyDestinationWritableFirstByte(void) { 1752 char source[100]; 1753 use_string(source); // escape 1754 char buf[100]; 1755 char *p = buf - 8; 1756 strncpy(p, source, 100-1); // expected-warning {{String copy function overflows the destination buffer}} 1757 } 1758 1759 void CWE124_Buffer_Underwrite__malloc_char_ncpy() { 1760 char * dataBuffer = (char *)malloc(100*sizeof(char)); 1761 if (dataBuffer == 0) return; 1762 memset(dataBuffer, 'A', 100-1); 1763 dataBuffer[100-1] = '\0'; 1764 char *data = dataBuffer - 8; 1765 1766 char source[100]; 1767 memset(source, 'C', 100-1); // fill with 'C's 1768 source[100-1] = '\0'; // null terminate 1769 strncpy(data, source, 100-1); // expected-warning {{String copy function overflows the destination buffer}} 1770 data[100-1] = '\0'; // null terminate 1771 free(dataBuffer); 1772 } 1773 #endif 1774 1775 #ifndef SUPPRESS_OUT_OF_BOUND 1776 void CWE124_Buffer_Underwrite__malloc_char_memcpy() { 1777 char * dataBuffer = (char *)malloc(100*sizeof(char)); 1778 if (dataBuffer == NULL) return; 1779 memset(dataBuffer, 'A', 100-1); 1780 dataBuffer[100-1] = '\0'; 1781 char *data = dataBuffer - 8; 1782 1783 char source[100]; 1784 memset(source, 'C', 100-1); // fill with 'C's 1785 source[100-1] = '\0'; // null terminate 1786 1787 memcpy(data, source, 100*sizeof(char)); // expected-warning {{Memory copy function overflows the destination buffer}} 1788 data[100-1] = '\0'; 1789 free(dataBuffer); 1790 } 1791 #endif 1792