1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,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,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
3 // RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,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,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
6 //===----------------------------------------------------------------------===
8 //===----------------------------------------------------------------------===
10 // Some functions are so similar to each other that they follow the same code
11 // path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is
12 // defined, make sure to use the variants instead to make sure they are still
13 // checked by the analyzer.
15 // Some functions are implemented as builtins. These should be #defined as
16 // BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.
18 // Functions that have variants and are also available as builtins should be
19 // declared carefully! See memcpy() for an example.
22 # define BUILTIN(f) __builtin_ ## f
23 #else /* USE_BUILTINS */
25 #endif /* USE_BUILTINS */
28 typedef typeof(sizeof(int)) size_t;
30 void clang_analyzer_eval(int);
32 int scanf(const char *restrict format, ...);
34 //===----------------------------------------------------------------------===
36 //===----------------------------------------------------------------------===
38 #define strlen BUILTIN(strlen)
39 size_t strlen(const char *s);
41 void strlen_constant0() {
42 clang_analyzer_eval(strlen("123") == 3); // expected-warning{{TRUE}}
45 void strlen_constant1() {
46 const char *a = "123";
47 clang_analyzer_eval(strlen(a) == 3); // expected-warning{{TRUE}}
50 void strlen_constant2(char x) {
52 clang_analyzer_eval(strlen(a) == 3); // expected-warning{{TRUE}}
55 clang_analyzer_eval(strlen(a) == 3); // expected-warning{{UNKNOWN}}
58 size_t strlen_null() {
59 return strlen(0); // expected-warning{{Null pointer argument in call to string length function}}
63 return strlen((char*)&strlen_fn); // expected-warning{{Argument to string length function is the address of the function 'strlen_fn', which is not a null-terminated string}}
66 size_t strlen_nonloc() {
68 return strlen((char*)&&label); // expected-warning{{Argument to string length function is the address of the label 'label', which is not a null-terminated string}}
71 void strlen_subregion() {
72 struct two_strings { char a[2], b[2]; };
73 extern void use_two_strings(struct two_strings *);
78 size_t a = strlen(z.a);
80 size_t b = strlen(z.a);
82 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
86 size_t c = strlen(z.a);
88 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
91 extern void use_string(char *);
92 void strlen_argument(char *x) {
96 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
100 size_t c = strlen(x);
102 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
105 extern char global_str[];
106 void strlen_global() {
107 size_t a = strlen(global_str);
108 size_t b = strlen(global_str);
110 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
111 // Make sure clang_analyzer_eval does not invalidate globals.
112 clang_analyzer_eval(strlen(global_str) == 0); // expected-warning{{TRUE}}
115 // Call a function with unknown effects, which should invalidate globals.
118 size_t c = strlen(global_str);
120 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
123 void strlen_indirect(char *x) {
124 size_t a = strlen(x);
127 size_t b = strlen(x);
129 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
131 extern void use_string_ptr(char*const*);
134 size_t c = strlen(x);
136 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
139 void strlen_indirect2(char *x) {
140 size_t a = strlen(x);
143 extern void use_string_ptr2(char**);
146 size_t c = strlen(x);
148 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
151 void strlen_liveness(const char *x) {
154 clang_analyzer_eval(strlen(x) < 5); // expected-warning{{FALSE}}
158 size_t strlenWrapper(const char *str) {
162 extern void invalidate(char *s);
164 void testStrlenCallee() {
167 size_t lenBefore = strlenWrapper(str);
169 size_t lenAfter = strlenWrapper(str);
170 clang_analyzer_eval(lenBefore == lenAfter); // expected-warning{{UNKNOWN}}
174 //===----------------------------------------------------------------------===
176 //===----------------------------------------------------------------------===
178 size_t strnlen(const char *s, size_t maxlen);
180 void strnlen_constant0() {
181 clang_analyzer_eval(strnlen("123", 10) == 3); // expected-warning{{TRUE}}
184 void strnlen_constant1() {
185 const char *a = "123";
186 clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{TRUE}}
189 void strnlen_constant2(char x) {
191 clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{TRUE}}
193 clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{UNKNOWN}}
196 void strnlen_constant4() {
197 clang_analyzer_eval(strnlen("123456", 3) == 3); // expected-warning{{TRUE}}
200 void strnlen_constant5() {
201 const char *a = "123456";
202 clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{TRUE}}
205 void strnlen_constant6(char x) {
207 clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{TRUE}}
209 clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{UNKNOWN}}
212 size_t strnlen_null() {
213 return strnlen(0, 3); // expected-warning{{Null pointer argument in call to string length function}}
216 size_t strnlen_fn() {
217 return strnlen((char*)&strlen_fn, 3); // expected-warning{{Argument to string length function is the address of the function 'strlen_fn', which is not a null-terminated string}}
220 size_t strnlen_nonloc() {
222 return strnlen((char*)&&label, 3); // expected-warning{{Argument to string length function is the address of the label 'label', which is not a null-terminated string}}
225 void strnlen_zero() {
226 clang_analyzer_eval(strnlen("abc", 0) == 0); // expected-warning{{TRUE}}
227 clang_analyzer_eval(strnlen(NULL, 0) == 0); // expected-warning{{TRUE}}
230 size_t strnlen_compound_literal() {
231 // This used to crash because we don't model the string lengths of
232 // compound literals.
233 return strnlen((char[]) { 'a', 'b', 0 }, 1);
236 size_t strnlen_unknown_limit(float f) {
237 // This used to crash because we don't model the integer values of floats.
238 return strnlen("abc", (int)f);
241 void strnlen_is_not_strlen(char *x) {
242 clang_analyzer_eval(strnlen(x, 10) == strlen(x)); // expected-warning{{UNKNOWN}}
245 void strnlen_at_limit(char *x) {
246 size_t len = strnlen(x, 10);
247 clang_analyzer_eval(len <= 10); // expected-warning{{TRUE}}
248 clang_analyzer_eval(len == 10); // expected-warning{{UNKNOWN}}
249 clang_analyzer_eval(len < 10); // expected-warning{{UNKNOWN}}
252 void strnlen_at_actual(size_t limit) {
253 size_t len = strnlen("abc", limit);
254 clang_analyzer_eval(len <= 3); // expected-warning{{TRUE}}
255 // This is due to eager assertion in strnlen.
257 clang_analyzer_eval(len == 0); // expected-warning{{TRUE}}
259 clang_analyzer_eval(len == 3); // expected-warning{{UNKNOWN}}
260 clang_analyzer_eval(len < 3); // expected-warning{{UNKNOWN}}
264 //===----------------------------------------------------------------------===
266 //===----------------------------------------------------------------------===
270 #define __strcpy_chk BUILTIN(__strcpy_chk)
271 char *__strcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen);
273 #define strcpy(a,b) __strcpy_chk(a,b,(size_t)-1)
277 #define strcpy BUILTIN(strcpy)
278 char *strcpy(char *restrict s1, const char *restrict s2);
283 void strcpy_null_dst(char *x) {
284 strcpy(NULL, x); // expected-warning{{Null pointer argument in call to string copy function}}
287 void strcpy_null_src(char *x) {
288 strcpy(x, NULL); // expected-warning{{Null pointer argument in call to string copy function}}
291 void strcpy_fn(char *x) {
292 strcpy(x, (char*)&strcpy_fn); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
295 void strcpy_fn_const(char *x) {
296 strcpy(x, (const char*)&strcpy_fn); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
299 extern int globalInt;
300 void strcpy_effects(char *x, char *y) {
305 clang_analyzer_eval(strcpy(x, y) == x); // expected-warning{{TRUE}}
306 clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}}
307 clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
308 clang_analyzer_eval(globalInt == 42); // expected-warning{{TRUE}}
311 void strcpy_overflow(char *y) {
314 strcpy(x, y); // expected-warning{{String copy function overflows destination buffer}}
317 void strcpy_no_overflow(char *y) {
320 strcpy(x, y); // no-warning
323 //===----------------------------------------------------------------------===
325 //===----------------------------------------------------------------------===
329 #define __stpcpy_chk BUILTIN(__stpcpy_chk)
330 char *__stpcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen);
332 #define stpcpy(a,b) __stpcpy_chk(a,b,(size_t)-1)
336 #define stpcpy BUILTIN(stpcpy)
337 char *stpcpy(char *restrict s1, const char *restrict s2);
342 void stpcpy_effect(char *x, char *y) {
345 clang_analyzer_eval(stpcpy(x, y) == &x[strlen(y)]); // expected-warning{{TRUE}}
346 clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}}
347 clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
350 void stpcpy_overflow(char *y) {
353 stpcpy(x, y); // expected-warning{{String copy function overflows destination buffer}}
356 void stpcpy_no_overflow(char *y) {
359 stpcpy(x, y); // no-warning
362 //===----------------------------------------------------------------------===
364 //===----------------------------------------------------------------------===
368 #define __strcat_chk BUILTIN(__strcat_chk)
369 char *__strcat_chk(char *restrict s1, const char *restrict s2, size_t destlen);
371 #define strcat(a,b) __strcat_chk(a,b,(size_t)-1)
375 #define strcat BUILTIN(strcat)
376 char *strcat(char *restrict s1, const char *restrict s2);
381 void strcat_null_dst(char *x) {
382 strcat(NULL, x); // expected-warning{{Null pointer argument in call to string copy function}}
385 void strcat_null_src(char *x) {
386 strcat(x, NULL); // expected-warning{{Null pointer argument in call to string copy function}}
389 void strcat_fn(char *x) {
390 strcat(x, (char*)&strcat_fn); // expected-warning{{Argument to string copy function is the address of the function 'strcat_fn', which is not a null-terminated string}}
393 void strcat_effects(char *y) {
395 size_t orig_len = strlen(x);
401 clang_analyzer_eval(strcat(x, y) == x); // expected-warning{{TRUE}}
402 clang_analyzer_eval((int)strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}}
405 void strcat_overflow_0(char *y) {
408 strcat(x, y); // expected-warning{{String copy function overflows destination buffer}}
411 void strcat_overflow_1(char *y) {
414 strcat(x, y); // expected-warning{{String copy function overflows destination buffer}}
417 void strcat_overflow_2(char *y) {
420 strcat(x, y); // expected-warning{{String copy function overflows destination buffer}}
423 void strcat_no_overflow(char *y) {
426 strcat(x, y); // no-warning
429 void strcat_symbolic_dst_length(char *dst) {
431 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
434 void strcat_symbolic_dst_length_taint(char *dst) {
435 scanf("%s", dst); // Taint data.
437 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
440 void strcat_unknown_src_length(char *src, int offset) {
441 char dst[8] = "1234";
442 strcat(dst, &src[offset]);
443 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
446 // There is no strcat_unknown_dst_length because if we can't get a symbolic
447 // length for the "before" strlen, we won't be able to set one for "after".
449 void strcat_too_big(char *dst, char *src) {
450 // We assume this can never actually happen, so we don't get a warning.
451 if (strlen(dst) != (((size_t)0) - 2))
453 if (strlen(src) != 2)
459 //===----------------------------------------------------------------------===
461 //===----------------------------------------------------------------------===
465 #define __strncpy_chk BUILTIN(__strncpy_chk)
466 char *__strncpy_chk(char *restrict s1, const char *restrict s2, size_t n, size_t destlen);
468 #define strncpy(a,b,n) __strncpy_chk(a,b,n,(size_t)-1)
472 #define strncpy BUILTIN(strncpy)
473 char *strncpy(char *restrict s1, const char *restrict s2, size_t n);
478 void strncpy_null_dst(char *x) {
479 strncpy(NULL, x, 5); // expected-warning{{Null pointer argument in call to string copy function}}
482 void strncpy_null_src(char *x) {
483 strncpy(x, NULL, 5); // expected-warning{{Null pointer argument in call to string copy function}}
486 void strncpy_fn(char *x) {
487 strncpy(x, (char*)&strcpy_fn, 5); // expected-warning{{Argument to string copy function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
490 void strncpy_effects(char *x, char *y) {
493 clang_analyzer_eval(strncpy(x, y, 5) == x); // expected-warning{{TRUE}}
494 clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{UNKNOWN}}
495 clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
498 void strncpy_overflow(char *y) {
501 strncpy(x, y, 5); // expected-warning{{Size argument is greater than the length of the destination buffer}}
504 void strncpy_no_overflow(char *y) {
507 strncpy(x, y, 5); // expected-warning{{Size argument is greater than the length of the destination buffer}}
510 void strncpy_no_overflow2(char *y, int n) {
516 strncpy(x, y, n); // expected-warning{{Size argument is greater than the length of the destination buffer}}
519 void strncpy_truncate(char *y) {
522 strncpy(x, y, 3); // no-warning
525 void strncpy_no_truncate(char *y) {
528 strncpy(x, y, 3); // no-warning
531 void strncpy_exactly_matching_buffer(char *y) {
533 strncpy(x, y, 4); // no-warning
535 // strncpy does not null-terminate, so we have no idea what the strlen is
537 clang_analyzer_eval(strlen(x) > 4); // expected-warning{{UNKNOWN}}
540 void strncpy_zero(char *src) {
542 strncpy(dst, src, 0); // no-warning
545 void strncpy_empty() {
548 strncpy(dst, src, 4); // no-warning
551 //===----------------------------------------------------------------------===
553 //===----------------------------------------------------------------------===
557 #define __strncat_chk BUILTIN(__strncat_chk)
558 char *__strncat_chk(char *restrict s1, const char *restrict s2, size_t n, size_t destlen);
560 #define strncat(a,b,c) __strncat_chk(a,b,c, (size_t)-1)
564 #define strncat BUILTIN(strncat)
565 char *strncat(char *restrict s1, const char *restrict s2, size_t n);
570 void strncat_null_dst(char *x) {
571 strncat(NULL, x, 4); // expected-warning{{Null pointer argument in call to string copy function}}
574 void strncat_null_src(char *x) {
575 strncat(x, NULL, 4); // expected-warning{{Null pointer argument in call to string copy function}}
578 void strncat_fn(char *x) {
579 strncat(x, (char*)&strncat_fn, 4); // expected-warning{{Argument to string copy function is the address of the function 'strncat_fn', which is not a null-terminated string}}
582 void strncat_effects(char *y) {
584 size_t orig_len = strlen(x);
590 clang_analyzer_eval(strncat(x, y, strlen(y)) == x); // expected-warning{{TRUE}}
591 clang_analyzer_eval(strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}}
594 void strncat_overflow_0(char *y) {
597 strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
600 void strncat_overflow_1(char *y) {
603 strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
606 void strncat_overflow_2(char *y) {
609 strncat(x, y, strlen(y)); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
612 void strncat_overflow_3(char *y) {
615 strncat(x, y, 2); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
617 void strncat_no_overflow_1(char *y) {
620 strncat(x, y, strlen(y)); // no-warning
623 void strncat_no_overflow_2(char *y) {
626 strncat(x, y, 1); // no-warning
629 void strncat_symbolic_dst_length(char *dst) {
630 strncat(dst, "1234", 5);
631 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
634 void strncat_symbolic_src_length(char *src) {
635 char dst[8] = "1234";
636 strncat(dst, src, 3);
637 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
639 char dst2[8] = "1234";
640 strncat(dst2, src, 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
643 void strncat_unknown_src_length(char *src, int offset) {
644 char dst[8] = "1234";
645 strncat(dst, &src[offset], 3);
646 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
648 char dst2[8] = "1234";
649 strncat(dst2, &src[offset], 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
652 // There is no strncat_unknown_dst_length because if we can't get a symbolic
653 // length for the "before" strlen, we won't be able to set one for "after".
655 void strncat_symbolic_limit(unsigned limit) {
656 char dst[6] = "1234";
658 strncat(dst, src, limit); // no-warning
660 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
661 clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}}
664 void strncat_unknown_limit(float limit) {
665 char dst[6] = "1234";
667 strncat(dst, src, (size_t)limit); // no-warning
669 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
670 clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}}
673 void strncat_too_big(char *dst, char *src) {
674 // We assume this will never actually happen, so we don't get a warning.
675 if (strlen(dst) != (((size_t)0) - 2))
677 if (strlen(src) != 2)
679 strncat(dst, src, 2);
682 void strncat_zero(char *src) {
684 strncat(dst, src, 0); // no-warning
687 void strncat_empty() {
690 strncat(dst, src, 4); // no-warning
693 //===----------------------------------------------------------------------===
695 //===----------------------------------------------------------------------===
697 #define strcmp BUILTIN(strcmp)
698 int strcmp(const char * s1, const char * s2);
700 void strcmp_check_modelling() {
703 clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}}
704 clang_analyzer_eval(strcmp(x, y) <= 0); // expected-warning{{FALSE}}
705 clang_analyzer_eval(strcmp(x, y) > 1); // expected-warning{{UNKNOWN}}
707 clang_analyzer_eval(strcmp(y, x) < 0); // expected-warning{{TRUE}}
708 clang_analyzer_eval(strcmp(y, x) >= 0); // expected-warning{{FALSE}}
709 clang_analyzer_eval(strcmp(y, x) < -1); // expected-warning{{UNKNOWN}}
712 void strcmp_constant0() {
713 clang_analyzer_eval(strcmp("123", "123") == 0); // expected-warning{{TRUE}}
716 void strcmp_constant_and_var_0() {
718 clang_analyzer_eval(strcmp(x, "123") == 0); // expected-warning{{TRUE}}
721 void strcmp_constant_and_var_1() {
723 clang_analyzer_eval(strcmp("123", x) == 0); // expected-warning{{TRUE}}
729 clang_analyzer_eval(strcmp(x, y) == 0); // expected-warning{{TRUE}}
735 clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}}
741 clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}}
744 void strcmp_null_0() {
747 strcmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
750 void strcmp_null_1() {
753 strcmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
756 void strcmp_diff_length_0() {
759 clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}}
762 void strcmp_diff_length_1() {
765 clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}}
768 void strcmp_diff_length_2() {
771 clang_analyzer_eval(strcmp(x, y) > 0); // expected-warning{{TRUE}}
774 void strcmp_diff_length_3() {
777 clang_analyzer_eval(strcmp(x, y) < 0); // expected-warning{{TRUE}}
780 void strcmp_embedded_null () {
781 clang_analyzer_eval(strcmp("\0z", "\0y") == 0); // expected-warning{{TRUE}}
784 void strcmp_unknown_arg (char *unknown) {
785 clang_analyzer_eval(strcmp(unknown, unknown) == 0); // expected-warning{{TRUE}}
792 void function_pointer_cast_helper(char **a) {
793 strcmp("Hi", *a); // PR24951 crash
796 void strcmp_union_function_pointer_cast(union argument a) {
797 void (*fPtr)(union argument *) = (void (*)(union argument *))function_pointer_cast_helper;
802 //===----------------------------------------------------------------------===
804 //===----------------------------------------------------------------------===
806 #define strncmp BUILTIN(strncmp)
807 int strncmp(const char *s1, const char *s2, size_t n);
809 void strncmp_check_modelling() {
812 clang_analyzer_eval(strncmp(x, y, 2) > 0); // expected-warning{{TRUE}}
813 clang_analyzer_eval(strncmp(x, y, 2) <= 0); // expected-warning{{FALSE}}
814 clang_analyzer_eval(strncmp(x, y, 2) > 1); // expected-warning{{UNKNOWN}}
816 clang_analyzer_eval(strncmp(y, x, 2) < 0); // expected-warning{{TRUE}}
817 clang_analyzer_eval(strncmp(y, x, 2) >= 0); // expected-warning{{FALSE}}
818 clang_analyzer_eval(strncmp(y, x, 2) < -1); // expected-warning{{UNKNOWN}}
821 void strncmp_constant0() {
822 clang_analyzer_eval(strncmp("123", "123", 3) == 0); // expected-warning{{TRUE}}
825 void strncmp_constant_and_var_0() {
827 clang_analyzer_eval(strncmp(x, "123", 3) == 0); // expected-warning{{TRUE}}
830 void strncmp_constant_and_var_1() {
832 clang_analyzer_eval(strncmp("123", x, 3) == 0); // expected-warning{{TRUE}}
838 clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}}
844 clang_analyzer_eval(strncmp(x, y, 3) > 0); // expected-warning{{TRUE}}
850 clang_analyzer_eval(strncmp(x, y, 3) < 0); // expected-warning{{TRUE}}
853 void strncmp_null_0() {
856 strncmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
859 void strncmp_null_1() {
862 strncmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
865 void strncmp_diff_length_0() {
868 clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}}
871 void strncmp_diff_length_1() {
874 clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}}
877 void strncmp_diff_length_2() {
880 clang_analyzer_eval(strncmp(x, y, 5) > 0); // expected-warning{{TRUE}}
883 void strncmp_diff_length_3() {
886 clang_analyzer_eval(strncmp(x, y, 5) < 0); // expected-warning{{TRUE}}
889 void strncmp_diff_length_4() {
892 clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}}
895 void strncmp_diff_length_5() {
898 clang_analyzer_eval(strncmp(x, y, 3) < 0); // expected-warning{{TRUE}}
901 void strncmp_diff_length_6() {
904 clang_analyzer_eval(strncmp(x, y, 3) > 0); // expected-warning{{TRUE}}
907 void strncmp_embedded_null () {
908 clang_analyzer_eval(strncmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}}
911 //===----------------------------------------------------------------------===
913 //===----------------------------------------------------------------------===
915 #define strcasecmp BUILTIN(strcasecmp)
916 int strcasecmp(const char *s1, const char *s2);
918 void strcasecmp_check_modelling() {
921 clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}}
922 clang_analyzer_eval(strcasecmp(x, y) <= 0); // expected-warning{{FALSE}}
923 clang_analyzer_eval(strcasecmp(x, y) > 1); // expected-warning{{UNKNOWN}}
925 clang_analyzer_eval(strcasecmp(y, x) < 0); // expected-warning{{TRUE}}
926 clang_analyzer_eval(strcasecmp(y, x) >= 0); // expected-warning{{FALSE}}
927 clang_analyzer_eval(strcasecmp(y, x) < -1); // expected-warning{{UNKNOWN}}
930 void strcasecmp_constant0() {
931 clang_analyzer_eval(strcasecmp("abc", "Abc") == 0); // expected-warning{{TRUE}}
934 void strcasecmp_constant_and_var_0() {
936 clang_analyzer_eval(strcasecmp(x, "Abc") == 0); // expected-warning{{TRUE}}
939 void strcasecmp_constant_and_var_1() {
941 clang_analyzer_eval(strcasecmp("Abc", x) == 0); // expected-warning{{TRUE}}
944 void strcasecmp_0() {
947 clang_analyzer_eval(strcasecmp(x, y) == 0); // expected-warning{{TRUE}}
950 void strcasecmp_1() {
953 clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}}
956 void strcasecmp_2() {
959 clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}}
962 void strcasecmp_null_0() {
965 strcasecmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
968 void strcasecmp_null_1() {
971 strcasecmp(x, y); // expected-warning{{Null pointer argument in call to string comparison function}}
974 void strcasecmp_diff_length_0() {
977 clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}}
980 void strcasecmp_diff_length_1() {
983 clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}}
986 void strcasecmp_diff_length_2() {
989 clang_analyzer_eval(strcasecmp(x, y) > 0); // expected-warning{{TRUE}}
992 void strcasecmp_diff_length_3() {
995 clang_analyzer_eval(strcasecmp(x, y) < 0); // expected-warning{{TRUE}}
998 void strcasecmp_embedded_null () {
999 clang_analyzer_eval(strcasecmp("ab\0zz", "ab\0yy") == 0); // expected-warning{{TRUE}}
1002 //===----------------------------------------------------------------------===
1004 //===----------------------------------------------------------------------===
1006 #define strncasecmp BUILTIN(strncasecmp)
1007 int strncasecmp(const char *s1, const char *s2, size_t n);
1009 void strncasecmp_check_modelling() {
1012 clang_analyzer_eval(strncasecmp(x, y, 2) > 0); // expected-warning{{TRUE}}
1013 clang_analyzer_eval(strncasecmp(x, y, 2) <= 0); // expected-warning{{FALSE}}
1014 clang_analyzer_eval(strncasecmp(x, y, 2) > 1); // expected-warning{{UNKNOWN}}
1016 clang_analyzer_eval(strncasecmp(y, x, 2) < 0); // expected-warning{{TRUE}}
1017 clang_analyzer_eval(strncasecmp(y, x, 2) >= 0); // expected-warning{{FALSE}}
1018 clang_analyzer_eval(strncasecmp(y, x, 2) < -1); // expected-warning{{UNKNOWN}}
1021 void strncasecmp_constant0() {
1022 clang_analyzer_eval(strncasecmp("abc", "Abc", 3) == 0); // expected-warning{{TRUE}}
1025 void strncasecmp_constant_and_var_0() {
1027 clang_analyzer_eval(strncasecmp(x, "Abc", 3) == 0); // expected-warning{{TRUE}}
1030 void strncasecmp_constant_and_var_1() {
1032 clang_analyzer_eval(strncasecmp("Abc", x, 3) == 0); // expected-warning{{TRUE}}
1035 void strncasecmp_0() {
1038 clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}}
1041 void strncasecmp_1() {
1044 clang_analyzer_eval(strncasecmp(x, y, 3) > 0); // expected-warning{{TRUE}}
1047 void strncasecmp_2() {
1050 clang_analyzer_eval(strncasecmp(x, y, 3) < 0); // expected-warning{{TRUE}}
1053 void strncasecmp_null_0() {
1056 strncasecmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
1059 void strncasecmp_null_1() {
1062 strncasecmp(x, y, 3); // expected-warning{{Null pointer argument in call to string comparison function}}
1065 void strncasecmp_diff_length_0() {
1068 clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}}
1071 void strncasecmp_diff_length_1() {
1074 clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}}
1077 void strncasecmp_diff_length_2() {
1080 clang_analyzer_eval(strncasecmp(x, y, 5) > 0); // expected-warning{{TRUE}}
1083 void strncasecmp_diff_length_3() {
1086 clang_analyzer_eval(strncasecmp(x, y, 5) < 0); // expected-warning{{TRUE}}
1089 void strncasecmp_diff_length_4() {
1092 clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}}
1095 void strncasecmp_diff_length_5() {
1098 clang_analyzer_eval(strncasecmp(x, y, 3) < 0); // expected-warning{{TRUE}}
1101 void strncasecmp_diff_length_6() {
1104 clang_analyzer_eval(strncasecmp(x, y, 3) > 0); // expected-warning{{TRUE}}
1107 void strncasecmp_embedded_null () {
1108 clang_analyzer_eval(strncasecmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}}
1111 //===----------------------------------------------------------------------===
1113 //===----------------------------------------------------------------------===
1115 char *strsep(char **stringp, const char *delim);
1117 void strsep_null_delim(char *s) {
1118 strsep(&s, NULL); // expected-warning{{Null pointer argument in call to strsep()}}
1121 void strsep_null_search() {
1122 strsep(NULL, ""); // expected-warning{{Null pointer argument in call to strsep()}}
1125 void strsep_return_original_pointer(char *s) {
1127 char *result = strsep(&s, ""); // no-warning
1128 clang_analyzer_eval(original == result); // expected-warning{{TRUE}}
1131 void strsep_null_string() {
1133 char *result = strsep(&s, ""); // no-warning
1134 clang_analyzer_eval(result == NULL); // expected-warning{{TRUE}}
1137 void strsep_changes_input_pointer(char *s) {
1139 strsep(&s, ""); // no-warning
1140 clang_analyzer_eval(s == original); // expected-warning{{UNKNOWN}}
1141 clang_analyzer_eval(s == NULL); // expected-warning{{UNKNOWN}}
1143 // Check that the value is symbolic.
1145 clang_analyzer_eval(s == NULL); // expected-warning{{TRUE}}
1149 void strsep_changes_input_string() {
1152 clang_analyzer_eval(str[1] == 'b'); // expected-warning{{TRUE}}
1155 strsep(&s, "b"); // no-warning
1157 // The real strsep will change the first delimiter it finds into a NUL
1158 // character. For now, we just model the invalidation.
1159 clang_analyzer_eval(str[1] == 'b'); // expected-warning{{UNKNOWN}}
1162 //===----------------------------------------------------------------------===
1164 //===----------------------------------------------------------------------===
1166 // The analyzer_eval call below should evaluate to true. We are being too
1167 // aggressive in marking the (length of) src symbol dead. The length of dst
1168 // depends on src. This could be explicitely specified in the checker or the
1169 // logic for handling MetadataSymbol in SymbolManager needs to change.
1170 void strcat_symbolic_src_length(char *src) {
1171 char dst[8] = "1234";
1173 clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{UNKNOWN}}
1176 // The analyzer_eval call below should evaluate to true. Most likely the same
1177 // issue as the test above.
1178 void strncpy_exactly_matching_buffer2(char *y) {
1183 strncpy(x, y, 4); // no-warning
1185 // This time, we know that y fits in x anyway.
1186 clang_analyzer_eval(strlen(x) <= 3); // expected-warning{{UNKNOWN}}