1 // RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s
2 // RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s
3 // RUN: %clang_cc1 -analyze -DVARIANT -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s
4 // RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -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 availabe 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 //===----------------------------------------------------------------------===
32 //===----------------------------------------------------------------------===
34 #define strlen BUILTIN(strlen)
35 size_t strlen(const char *s
);
37 void strlen_constant0() {
38 if (strlen("123") != 3)
39 (void)*(char*)0; // no-warning
42 void strlen_constant1() {
43 const char *a
= "123";
45 (void)*(char*)0; // no-warning
48 void strlen_constant2(char x
) {
51 (void)*(char*)0; // no-warning
54 (void)*(char*)0; // expected-warning{{null}}
57 size_t strlen_null() {
58 return strlen(0); // expected-warning{{Null pointer argument in call to byte string function}}
62 return strlen((char*)&strlen_fn
); // expected-warning{{Argument to byte string function is the address of the function 'strlen_fn', which is not a null-terminated string}}
65 size_t strlen_nonloc() {
67 return strlen((char*)&&label
); // expected-warning{{Argument to byte string function is the address of the label 'label', which is not a null-terminated string}}
70 void strlen_subregion() {
71 struct two_strings
{ char a
[2], b
[2] };
72 extern void use_two_strings(struct two_strings
*);
77 size_t a
= strlen(z
.a
);
79 size_t b
= strlen(z
.a
);
81 (void)*(char*)0; // expected-warning{{never executed}}
85 size_t c
= strlen(z
.a
);
87 (void)*(char*)0; // expected-warning{{null}}
90 extern void use_string(char *);
91 void strlen_argument(char *x
) {
95 (void)*(char*)0; // expected-warning{{never executed}}
100 if (a
== 0 && c
!= 0)
101 (void)*(char*)0; // expected-warning{{null}}
104 extern char global_str
[];
105 void strlen_global() {
106 size_t a
= strlen(global_str
);
107 size_t b
= strlen(global_str
);
108 if (a
== 0 && b
!= 0)
109 (void)*(char*)0; // expected-warning{{never executed}}
111 // Call a function with unknown effects, which should invalidate globals.
114 size_t c
= strlen(global_str
);
115 if (a
== 0 && c
!= 0)
116 (void)*(char*)0; // expected-warning{{null}}
119 void strlen_indirect(char *x
) {
120 size_t a
= strlen(x
);
123 size_t b
= strlen(x
);
124 if (a
== 0 && b
!= 0)
125 (void)*(char*)0; // expected-warning{{never executed}}
127 extern void use_string_ptr(char*const*);
130 size_t c
= strlen(x
);
131 if (a
== 0 && c
!= 0)
132 (void)*(char*)0; // expected-warning{{null}}
135 void strlen_liveness(const char *x
) {
139 (void)*(char*)0; // no-warning
142 //===----------------------------------------------------------------------===
144 //===----------------------------------------------------------------------===
148 #define __strcpy_chk BUILTIN(__strcpy_chk)
149 char *__strcpy_chk(char *restrict s1
, const char *restrict s2
, size_t destlen
);
151 #define strcpy(a,b) __strcpy_chk(a,b,(size_t)-1)
155 #define strcpy BUILTIN(strcpy)
156 char *strcpy(char *restrict s1
, const char *restrict s2
);
161 void strcpy_null_dst(char *x
) {
162 strcpy(NULL
, x
); // expected-warning{{Null pointer argument in call to byte string function}}
165 void strcpy_null_src(char *x
) {
166 strcpy(x
, NULL
); // expected-warning{{Null pointer argument in call to byte string function}}
169 void strcpy_fn(char *x
) {
170 strcpy(x
, (char*)&strcpy_fn
); // expected-warning{{Argument to byte string function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
173 void strcpy_effects(char *x
, char *y
) {
176 if (strcpy(x
, y
) != x
)
177 (void)*(char*)0; // no-warning
179 if (strlen(x
) != strlen(y
))
180 (void)*(char*)0; // no-warning
183 (void)*(char*)0; // expected-warning{{null}}
186 void strcpy_overflow(char *y
) {
189 strcpy(x
, y
); // expected-warning{{Byte string function overflows destination buffer}}
192 void strcpy_no_overflow(char *y
) {
195 strcpy(x
, y
); // no-warning
198 //===----------------------------------------------------------------------===
200 //===----------------------------------------------------------------------===
204 #define __stpcpy_chk BUILTIN(__stpcpy_chk)
205 char *__stpcpy_chk(char *restrict s1
, const char *restrict s2
, size_t destlen
);
207 #define stpcpy(a,b) __stpcpy_chk(a,b,(size_t)-1)
211 #define stpcpy BUILTIN(stpcpy)
212 char *stpcpy(char *restrict s1
, const char *restrict s2
);
217 void stpcpy_effect(char *x
, char *y
) {
220 if (stpcpy(x
, y
) != &x
[strlen(y
)])
221 (void)*(char*)0; // no-warning
223 if (strlen(x
) != strlen(y
))
224 (void)*(char*)0; // no-warning
227 (void)*(char*)0; // expected-warning{{null}}
230 void stpcpy_overflow(char *y
) {
233 stpcpy(x
, y
); // expected-warning{{Byte string function overflows destination buffer}}
236 void stpcpy_no_overflow(char *y
) {
239 stpcpy(x
, y
); // no-warning