1 // RUN: %clang_analyze_cc1 -verify %s \
2 // RUN: -analyzer-checker=core \
3 // RUN: -analyzer-checker=unix.cstring \
4 // RUN: -analyzer-checker=alpha.unix.cstring \
5 // RUN: -analyzer-disable-checker=alpha.unix.cstring.UninitializedRead \
6 // RUN: -analyzer-checker=debug.ExprInspection \
7 // RUN: -analyzer-config eagerly-assume=false
8 //
9 // RUN: %clang_analyze_cc1 -verify %s -DUSE_BUILTINS \
10 // RUN: -analyzer-checker=core \
11 // RUN: -analyzer-checker=unix.cstring \
12 // RUN: -analyzer-checker=alpha.unix.cstring \
13 // RUN: -analyzer-disable-checker=alpha.unix.cstring.UninitializedRead \
14 // RUN: -analyzer-checker=debug.ExprInspection \
15 // RUN: -analyzer-config eagerly-assume=false
16
17 //===----------------------------------------------------------------------===
18 // Declarations
19 //===----------------------------------------------------------------------===
20
21 // Some functions are implemented as builtins. These should be #defined as
22 // BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.
23
24 #ifdef USE_BUILTINS
25 # define BUILTIN(f) __builtin_ ## f
26 #else /* USE_BUILTINS */
27 # define BUILTIN(f) f
28 #endif /* USE_BUILTINS */
29
30 typedef __SIZE_TYPE__ size_t;
31 typedef __WCHAR_TYPE__ wchar_t;
32
33 void clang_analyzer_eval(int);
34
35 //===----------------------------------------------------------------------===
36 // wwmemcpy()
37 //===----------------------------------------------------------------------===
38
39 #define wmemcpy BUILTIN(wmemcpy)
40 wchar_t *wmemcpy(wchar_t *restrict s1, const wchar_t *restrict s2, size_t n);
41
wmemcpy0(void)42 void wmemcpy0 (void) {
43 wchar_t src[] = {1, 2, 3, 4};
44 wchar_t dst[4] = {0};
45
46 wmemcpy(dst, src, 4); // no-warning
47
48 clang_analyzer_eval(wmemcpy(dst, src, 4) == dst); // expected-warning{{TRUE}}
49
50 // If we actually model the copy, we can make this known.
51 // The important thing for now is that the old value has been invalidated.
52 clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
53 }
54
wmemcpy1(void)55 void wmemcpy1 (void) {
56 wchar_t src[] = {1, 2, 3, 4};
57 wchar_t dst[10];
58
59 wmemcpy(dst, src, 5); // expected-warning{{Memory copy function accesses out-of-bound array element}}
60 }
61
wmemcpy2(void)62 void wmemcpy2 (void) {
63 wchar_t src[] = {1, 2, 3, 4};
64 wchar_t dst[1];
65
66 wmemcpy(dst, src, 4); // expected-warning {{Memory copy function overflows the destination buffer}}
67 }
68
wmemcpy3(void)69 void wmemcpy3 (void) {
70 wchar_t src[] = {1, 2, 3, 4};
71 wchar_t dst[3];
72
73 wmemcpy(dst+1, src+2, 2); // no-warning
74 }
75
wmemcpy4(void)76 void wmemcpy4 (void) {
77 wchar_t src[] = {1, 2, 3, 4};
78 wchar_t dst[10];
79
80 wmemcpy(dst+2, src+2, 3); // expected-warning{{Memory copy function accesses out-of-bound array element}}
81 }
82
wmemcpy5(void)83 void wmemcpy5(void) {
84 wchar_t src[] = {1, 2, 3, 4};
85 wchar_t dst[3];
86
87 wmemcpy(dst + 2, src + 2, 2); // expected-warning{{Memory copy function overflows the destination buffer}}
88 }
89
wmemcpy6(void)90 void wmemcpy6(void) {
91 wchar_t a[4] = {0};
92 wmemcpy(a, a, 2); // expected-warning{{overlapping}}
93 }
94
wmemcpy7(void)95 void wmemcpy7(void) {
96 wchar_t a[4] = {0};
97 wmemcpy(a+2, a+1, 2); // expected-warning{{overlapping}}
98 }
99
wmemcpy8(void)100 void wmemcpy8(void) {
101 wchar_t a[4] = {0};
102 wmemcpy(a+1, a+2, 2); // expected-warning{{overlapping}}
103 }
104
wmemcpy9(void)105 void wmemcpy9(void) {
106 wchar_t a[4] = {0};
107 wmemcpy(a+2, a+1, 1); // no-warning
108 wmemcpy(a+1, a+2, 1); // no-warning
109 }
110
wmemcpy10(void)111 void wmemcpy10(void) {
112 wchar_t a[4] = {0};
113 wmemcpy(0, a, 1); // expected-warning{{Null pointer passed as 1st argument to memory copy function}}
114 }
115
wmemcpy11(void)116 void wmemcpy11(void) {
117 wchar_t a[4] = {0};
118 wmemcpy(a, 0, 1); // expected-warning{{Null pointer passed as 2nd argument to memory copy function}}
119 }
120
wmemcpy12(void)121 void wmemcpy12(void) {
122 wchar_t a[4] = {0};
123 wmemcpy(0, a, 0); // no-warning
124 }
125
wmemcpy13(void)126 void wmemcpy13(void) {
127 wchar_t a[4] = {0};
128 wmemcpy(a, 0, 0); // no-warning
129 }
130
wmemcpy_unknown_size(size_t n)131 void wmemcpy_unknown_size (size_t n) {
132 wchar_t a[4], b[4] = {1};
133 clang_analyzer_eval(wmemcpy(a, b, n) == a); // expected-warning{{TRUE}}
134 }
135
wmemcpy_unknown_size_warn(size_t n)136 void wmemcpy_unknown_size_warn (size_t n) {
137 wchar_t a[4];
138 void *result = wmemcpy(a, 0, n); // expected-warning{{Null pointer passed as 2nd argument to memory copy function}}
139 clang_analyzer_eval(result == a); // no-warning (above is fatal)
140 }
141
142 //===----------------------------------------------------------------------===
143 // wcslen()
144 //===----------------------------------------------------------------------===
145
146 #define wcslen BUILTIN(wcslen)
147 size_t wcslen(const wchar_t *s);
148
wcslen_constant0(void)149 void wcslen_constant0(void) {
150 clang_analyzer_eval(wcslen(L"123") == 3); // expected-warning{{TRUE}}
151 }
152
wcslen_constant1(void)153 void wcslen_constant1(void) {
154 const wchar_t *a = L"123";
155 clang_analyzer_eval(wcslen(a) == 3); // expected-warning{{TRUE}}
156 }
157
wcslen_constant2(wchar_t x)158 void wcslen_constant2(wchar_t x) {
159 wchar_t a[] = L"123";
160 clang_analyzer_eval(wcslen(a) == 3); // expected-warning{{TRUE}}
161
162 a[0] = x;
163 clang_analyzer_eval(wcslen(a) == 3); // expected-warning{{UNKNOWN}}
164 }
165
wcslen_null(void)166 size_t wcslen_null(void) {
167 return wcslen(0); // expected-warning{{Null pointer passed as 1st argument to string length function}}
168 }
169
wcslen_fn(void)170 size_t wcslen_fn(void) {
171 return wcslen((wchar_t*)&wcslen_fn); // expected-warning{{Argument to string length function is the address of the function 'wcslen_fn', which is not a null-terminated string}}
172 }
173
wcslen_nonloc(void)174 size_t wcslen_nonloc(void) {
175 label:
176 return wcslen((wchar_t*)&&label); // expected-warning{{Argument to string length function is the address of the label 'label', which is not a null-terminated string}}
177 }
178
wcslen_subregion(void)179 void wcslen_subregion(void) {
180 struct two_strings { wchar_t a[2], b[2]; };
181 extern void use_two_strings(struct two_strings *);
182
183 struct two_strings z;
184 use_two_strings(&z);
185
186 size_t a = wcslen(z.a);
187 z.b[0] = 5;
188 size_t b = wcslen(z.a);
189 if (a == 0)
190 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
191
192 use_two_strings(&z);
193
194 size_t c = wcslen(z.a);
195 if (a == 0)
196 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
197 }
198
199 extern void use_string(wchar_t *);
wcslen_argument(wchar_t * x)200 void wcslen_argument(wchar_t *x) {
201 size_t a = wcslen(x);
202 size_t b = wcslen(x);
203 if (a == 0)
204 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
205
206 use_string(x);
207
208 size_t c = wcslen(x);
209 if (a == 0)
210 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
211 }
212
213 extern wchar_t global_str[];
wcslen_global(void)214 void wcslen_global(void) {
215 size_t a = wcslen(global_str);
216 size_t b = wcslen(global_str);
217 if (a == 0) {
218 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
219 // Make sure clang_analyzer_eval does not invalidate globals.
220 clang_analyzer_eval(wcslen(global_str) == 0); // expected-warning{{TRUE}}
221 }
222
223 // Call a function with unknown effects, which should invalidate globals.
224 use_string(0);
225
226 size_t c = wcslen(global_str);
227 if (a == 0)
228 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
229 }
230
wcslen_indirect(wchar_t * x)231 void wcslen_indirect(wchar_t *x) {
232 size_t a = wcslen(x);
233 wchar_t *p = x;
234 wchar_t **p2 = &p;
235 size_t b = wcslen(x);
236 if (a == 0)
237 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
238
239 extern void use_string_ptr(wchar_t*const*);
240 use_string_ptr(p2);
241
242 size_t c = wcslen(x);
243 if (a == 0)
244 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
245 }
246
wcslen_indirect2(wchar_t * x)247 void wcslen_indirect2(wchar_t *x) {
248 size_t a = wcslen(x);
249 wchar_t *p = x;
250 wchar_t **p2 = &p;
251 extern void use_string_ptr2(wchar_t**);
252 use_string_ptr2(p2);
253
254 size_t c = wcslen(x);
255 if (a == 0)
256 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
257 }
258
wcslen_liveness(const wchar_t * x)259 void wcslen_liveness(const wchar_t *x) {
260 if (wcslen(x) < 5)
261 return;
262 clang_analyzer_eval(wcslen(x) < 5); // expected-warning{{FALSE}}
263 }
264
265
wcslenWrapper(const wchar_t * str)266 size_t wcslenWrapper(const wchar_t *str) {
267 return wcslen(str);
268 }
269
270 extern void invalidate(wchar_t *s);
271
testwcslenCallee(void)272 void testwcslenCallee(void) {
273 wchar_t str[42];
274 invalidate(str);
275 size_t lenBefore = wcslenWrapper(str);
276 invalidate(str);
277 size_t lenAfter = wcslenWrapper(str);
278 clang_analyzer_eval(lenBefore == lenAfter); // expected-warning{{UNKNOWN}}
279 }
280
281 //===----------------------------------------------------------------------===
282 // wcsnlen()
283 //===----------------------------------------------------------------------===
284
285 size_t wcsnlen(const wchar_t *s, size_t maxlen);
286
wcsnlen_constant0(void)287 void wcsnlen_constant0(void) {
288 clang_analyzer_eval(wcsnlen(L"123", 10) == 3); // expected-warning{{TRUE}}
289 }
290
wcsnlen_constant1(void)291 void wcsnlen_constant1(void) {
292 const wchar_t *a = L"123";
293 clang_analyzer_eval(wcsnlen(a, 10) == 3); // expected-warning{{TRUE}}
294 }
295
wcsnlen_constant2(char x)296 void wcsnlen_constant2(char x) {
297 wchar_t a[] = L"123";
298 clang_analyzer_eval(wcsnlen(a, 10) == 3); // expected-warning{{TRUE}}
299 a[0] = x;
300 clang_analyzer_eval(wcsnlen(a, 10) == 3); // expected-warning{{UNKNOWN}}
301 }
302
wcsnlen_constant4(void)303 void wcsnlen_constant4(void) {
304 clang_analyzer_eval(wcsnlen(L"123456", 3) == 3); // expected-warning{{TRUE}}
305 }
306
wcsnlen_constant5(void)307 void wcsnlen_constant5(void) {
308 const wchar_t *a = L"123456";
309 clang_analyzer_eval(wcsnlen(a, 3) == 3); // expected-warning{{TRUE}}
310 }
311
wcsnlen_constant6(char x)312 void wcsnlen_constant6(char x) {
313 wchar_t a[] = L"123456";
314 clang_analyzer_eval(wcsnlen(a, 3) == 3); // expected-warning{{TRUE}}
315 a[0] = x;
316 clang_analyzer_eval(wcsnlen(a, 3) == 3); // expected-warning{{UNKNOWN}}
317 }
318
wcsnlen_null(void)319 size_t wcsnlen_null(void) {
320 return wcsnlen(0, 3); // expected-warning{{Null pointer passed as 1st argument to string length function}}
321 }
322
wcsnlen_fn(void)323 size_t wcsnlen_fn(void) {
324 return wcsnlen((wchar_t*)&wcsnlen_fn, 3); // expected-warning{{Argument to string length function is the address of the function 'wcsnlen_fn', which is not a null-terminated string}}
325 }
326
wcsnlen_nonloc(void)327 size_t wcsnlen_nonloc(void) {
328 label:
329 return wcsnlen((wchar_t*)&&label, 3); // expected-warning{{Argument to string length function is the address of the label 'label', which is not a null-terminated string}}
330 }
331
wcsnlen_zero(void)332 void wcsnlen_zero(void) {
333 clang_analyzer_eval(wcsnlen(L"abc", 0) == 0); // expected-warning{{TRUE}}
334 clang_analyzer_eval(wcsnlen(0, 0) == 0); // expected-warning{{TRUE}}
335 }
336
wcsnlen_compound_literal(void)337 size_t wcsnlen_compound_literal(void) {
338 // This used to crash because we don't model the string lengths of
339 // compound literals.
340 return wcsnlen((wchar_t[]) { 'a', 'b', 0 }, 1);
341 }
342
wcsnlen_unknown_limit(float f)343 size_t wcsnlen_unknown_limit(float f) {
344 // This used to crash because we don't model the integer values of floats.
345 return wcsnlen(L"abc", (int)f);
346 }
347
wcsnlen_is_not_wcslen(wchar_t * x)348 void wcsnlen_is_not_wcslen(wchar_t *x) {
349 clang_analyzer_eval(wcsnlen(x, 10) == wcslen(x)); // expected-warning{{UNKNOWN}}
350 }
351
wcsnlen_at_limit(wchar_t * x)352 void wcsnlen_at_limit(wchar_t *x) {
353 size_t len = wcsnlen(x, 10);
354 clang_analyzer_eval(len <= 10); // expected-warning{{TRUE}}
355 clang_analyzer_eval(len == 10); // expected-warning{{UNKNOWN}}
356 clang_analyzer_eval(len < 10); // expected-warning{{UNKNOWN}}
357 }
358
wcsnlen_at_actual(size_t limit)359 void wcsnlen_at_actual(size_t limit) {
360 size_t len = wcsnlen(L"abc", limit);
361 clang_analyzer_eval(len <= 3); // expected-warning{{TRUE}}
362 // This is due to eager assertion in wcsnlen.
363 if (limit == 0) {
364 clang_analyzer_eval(len == 0); // expected-warning{{TRUE}}
365 } else {
366 clang_analyzer_eval(len == 3); // expected-warning{{UNKNOWN}}
367 clang_analyzer_eval(len < 3); // expected-warning{{UNKNOWN}}
368 }
369 }
370
371 //===----------------------------------------------------------------------===
372 // other tests
373 //===----------------------------------------------------------------------===
374
375 static const wchar_t w_str[] = L"Hello world";
376
wmemcpy_sizeof(void)377 void wmemcpy_sizeof(void) {
378 wchar_t a[32];
379 wmemcpy(a, w_str, sizeof(w_str) / sizeof(w_str[0]));
380 wmemcpy(a, w_str, (sizeof(w_str) / sizeof(w_str[0])) + 1); // expected-warning {{Memory copy function accesses out-of-bound array element}}
381 }
382
wmemcpy_wcslen(void)383 void wmemcpy_wcslen(void) {
384 wchar_t a[32];
385 // FIXME: This should work with 'w_str' instead of 'w_str1'
386 const wchar_t w_str1[] = L"Hello world";
387 wmemcpy(a, w_str1, wcslen(w_str1) + 1);
388 wmemcpy(a, w_str1, wcslen(w_str1) + 2); // expected-warning {{Memory copy function accesses out-of-bound array element}}
389 }
390