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