[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / Analysis / wstring.c
blob9c60d39ff502e98f48e6b81893399ab0b84f1a02
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
17 //===----------------------------------------------------------------------===
18 // Declarations
19 //===----------------------------------------------------------------------===
21 // Some functions are implemented as builtins. These should be #defined as
22 // BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.
24 #ifdef USE_BUILTINS
25 # define BUILTIN(f) __builtin_ ## f
26 #else /* USE_BUILTINS */
27 # define BUILTIN(f) f
28 #endif /* USE_BUILTINS */
30 typedef __SIZE_TYPE__ size_t;
31 typedef __WCHAR_TYPE__ wchar_t;
33 void clang_analyzer_eval(int);
35 //===----------------------------------------------------------------------===
36 // wmemcpy()
37 //===----------------------------------------------------------------------===
39 #define wmemcpy BUILTIN(wmemcpy)
40 wchar_t *wmemcpy(wchar_t *restrict s1, const wchar_t *restrict s2, size_t n);
42 void wmemcpy0 (void) {
43 wchar_t src[] = {1, 2, 3, 4};
44 wchar_t dst[4] = {0};
46 wmemcpy(dst, src, 4); // no-warning
48 clang_analyzer_eval(wmemcpy(dst, src, 4) == dst); // expected-warning{{TRUE}}
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}}
55 void wmemcpy1 (void) {
56 wchar_t src[] = {1, 2, 3, 4};
57 wchar_t dst[10];
59 wmemcpy(dst, src, 5); // expected-warning{{Memory copy function accesses out-of-bound array element}}
62 void wmemcpy2 (void) {
63 wchar_t src[] = {1, 2, 3, 4};
64 wchar_t dst[1];
66 wmemcpy(dst, src, 4); // expected-warning {{Memory copy function overflows the destination buffer}}
69 void wmemcpy3 (void) {
70 wchar_t src[] = {1, 2, 3, 4};
71 wchar_t dst[3];
73 wmemcpy(dst+1, src+2, 2); // no-warning
76 void wmemcpy4 (void) {
77 wchar_t src[] = {1, 2, 3, 4};
78 wchar_t dst[10];
80 wmemcpy(dst+2, src+2, 3); // expected-warning{{Memory copy function accesses out-of-bound array element}}
83 void wmemcpy5(void) {
84 wchar_t src[] = {1, 2, 3, 4};
85 wchar_t dst[3];
87 wmemcpy(dst + 2, src + 2, 2); // expected-warning{{Memory copy function overflows the destination buffer}}
90 void wmemcpy6(void) {
91 wchar_t a[4] = {0};
92 wmemcpy(a, a, 2); // expected-warning{{overlapping}}
95 void wmemcpy7(void) {
96 wchar_t a[4] = {0};
97 wmemcpy(a+2, a+1, 2); // expected-warning{{overlapping}}
100 void wmemcpy8(void) {
101 wchar_t a[4] = {0};
102 wmemcpy(a+1, a+2, 2); // expected-warning{{overlapping}}
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
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}}
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}}
121 void wmemcpy12(void) {
122 wchar_t a[4] = {0};
123 wmemcpy(0, a, 0); // no-warning
126 void wmemcpy13(void) {
127 wchar_t a[4] = {0};
128 wmemcpy(a, 0, 0); // no-warning
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}}
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)
142 //===----------------------------------------------------------------------===
143 // wmempcpy()
144 //===----------------------------------------------------------------------===
146 wchar_t *wmempcpy(wchar_t *restrict s1, const wchar_t *restrict s2, size_t n);
148 void wmempcpy0 (void) {
149 wchar_t src[] = {1, 2, 3, 4};
150 wchar_t dst[5] = {0};
152 wmempcpy(dst, src, 4); // no-warning
154 clang_analyzer_eval(wmempcpy(dst, src, 4) == &dst[4]); // expected-warning{{TRUE}}
156 // If we actually model the copy, we can make this known.
157 // The important thing for now is that the old value has been invalidated.
158 clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
161 void wmempcpy1 (void) {
162 wchar_t src[] = {1, 2, 3, 4};
163 wchar_t dst[10];
165 wmempcpy(dst, src, 5); // expected-warning{{Memory copy function accesses out-of-bound array element}}
168 void wmempcpy2 (void) {
169 wchar_t src[] = {1, 2, 3, 4};
170 wchar_t dst[1];
172 wmempcpy(dst, src, 4); // expected-warning{{Memory copy function overflows the destination buffer}}
175 void wmempcpy3 (void) {
176 wchar_t src[] = {1, 2, 3, 4};
177 wchar_t dst[3];
179 wmempcpy(dst+1, src+2, 2); // no-warning
182 void wmempcpy4 (void) {
183 wchar_t src[] = {1, 2, 3, 4};
184 wchar_t dst[10];
186 wmempcpy(dst+2, src+2, 3); // expected-warning{{Memory copy function accesses out-of-bound array element}}
189 void wmempcpy5(void) {
190 wchar_t src[] = {1, 2, 3, 4};
191 wchar_t dst[3];
193 wmempcpy(dst + 2, src + 2, 2); // expected-warning{{Memory copy function overflows the destination buffer}}
196 void wmempcpy6(void) {
197 wchar_t a[4] = {0};
198 wmempcpy(a, a, 2); // expected-warning{{overlapping}}
201 void wmempcpy7(void) {
202 wchar_t a[4] = {0};
203 wmempcpy(a+2, a+1, 2); // expected-warning{{overlapping}}
206 void wmempcpy8(void) {
207 wchar_t a[4] = {0};
208 wmempcpy(a+1, a+2, 2); // expected-warning{{overlapping}}
211 void wmempcpy9(void) {
212 wchar_t a[4] = {0};
213 wmempcpy(a+2, a+1, 1); // no-warning
214 wmempcpy(a+1, a+2, 1); // no-warning
217 void wmempcpy10(void) {
218 wchar_t a[4] = {0};
219 wmempcpy(0, a, 1); // expected-warning{{Null pointer passed as 1st argument to memory copy function}}
222 void wmempcpy11(void) {
223 wchar_t a[4] = {0};
224 wmempcpy(a, 0, 1); // expected-warning{{Null pointer passed as 2nd argument to memory copy function}}
227 void wmempcpy12(void) {
228 wchar_t a[4] = {0};
229 wmempcpy(0, a, 0); // no-warning
232 void wmempcpy13(void) {
233 wchar_t a[4] = {0};
234 wmempcpy(a, 0, 0); // no-warning
237 void wmempcpy14(void) {
238 wchar_t src[] = {1, 2, 3, 4};
239 wchar_t dst[5] = {0};
240 wchar_t *p;
242 p = wmempcpy(dst, src, 4);
244 clang_analyzer_eval(p == &dst[4]); // expected-warning{{TRUE}}
247 struct st {
248 wchar_t i;
249 wchar_t j;
252 void wmempcpy15(void) {
253 struct st s1 = {0};
254 struct st s2;
255 struct st *p1;
256 struct st *p2;
258 p1 = (&s2) + 1;
259 p2 = (struct st *)wmempcpy((wchar_t *)&s2, (wchar_t *)&s1, 2);
261 clang_analyzer_eval(p1 == p2); // expected-warning{{TRUE}}
264 void wmempcpy16(void) {
265 struct st s1[10] = {{0}};
266 struct st s2[10];
267 struct st *p1;
268 struct st *p2;
270 p1 = (&s2[0]) + 5;
271 p2 = (struct st *)wmempcpy((wchar_t *)&s2[0], (wchar_t *)&s1[0], 5 * 2);
273 clang_analyzer_eval(p1 == p2); // expected-warning{{TRUE}}
276 void wmempcpy_unknown_size_warn (size_t n) {
277 wchar_t a[4];
278 void *result = wmempcpy(a, 0, n); // expected-warning{{Null pointer passed as 2nd argument to memory copy function}}
279 clang_analyzer_eval(result == a); // no-warning (above is fatal)
282 void wmempcpy_unknownable_size (wchar_t *src, float n) {
283 wchar_t a[4];
284 // This used to crash because we don't model floats.
285 wmempcpy(a, src, (size_t)n);
288 //===----------------------------------------------------------------------===
289 // wmemmove()
290 //===----------------------------------------------------------------------===
292 #define wmemmove BUILTIN(wmemmove)
293 wchar_t *wmemmove(wchar_t *s1, const wchar_t *s2, size_t n);
295 void wmemmove0 (void) {
296 wchar_t src[] = {1, 2, 3, 4};
297 wchar_t dst[4] = {0};
299 wmemmove(dst, src, 4); // no-warning
301 clang_analyzer_eval(wmemmove(dst, src, 4) == dst); // expected-warning{{TRUE}}
303 clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
306 void wmemmove1 (void) {
307 wchar_t src[] = {1, 2, 3, 4};
308 wchar_t dst[10];
310 wmemmove(dst, src, 5); // expected-warning{{out-of-bound}}
313 void wmemmove2 (void) {
314 wchar_t src[] = {1, 2, 3, 4};
315 wchar_t dst[1];
317 wmemmove(dst, src, 4); // expected-warning{{Memory copy function overflows the destination buffer}}
320 //===----------------------------------------------------------------------===
321 // wmemcmp()
322 //===----------------------------------------------------------------------===
324 #define wmemcmp BUILTIN(wmemcmp)
325 int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n);
327 void wmemcmp0 (void) {
328 wchar_t a[] = {1, 2, 3, 4};
329 wchar_t b[4] = { 0 };
331 wmemcmp(a, b, 4); // no-warning
334 void wmemcmp1 (void) {
335 wchar_t a[] = {1, 2, 3, 4};
336 wchar_t b[10] = { 0 };
338 wmemcmp(a, b, 5); // expected-warning{{out-of-bound}}
341 void wmemcmp2 (void) {
342 wchar_t a[] = {1, 2, 3, 4};
343 wchar_t b[1] = { 0 };
345 wmemcmp(a, b, 4); // expected-warning{{out-of-bound}}
348 void wmemcmp3 (void) {
349 wchar_t a[] = {1, 2, 3, 4};
351 clang_analyzer_eval(wmemcmp(a, a, 4) == 0); // expected-warning{{TRUE}}
354 void wmemcmp4 (wchar_t *input) {
355 wchar_t a[] = {1, 2, 3, 4};
357 clang_analyzer_eval(wmemcmp(a, input, 4) == 0); // expected-warning{{UNKNOWN}}
360 void wmemcmp5 (wchar_t *input) {
361 wchar_t a[] = {1, 2, 3, 4};
363 clang_analyzer_eval(wmemcmp(a, 0, 0) == 0); // expected-warning{{TRUE}}
364 clang_analyzer_eval(wmemcmp(0, a, 0) == 0); // expected-warning{{TRUE}}
365 clang_analyzer_eval(wmemcmp(a, input, 0) == 0); // expected-warning{{TRUE}}
368 void wmemcmp6 (wchar_t *a, wchar_t *b, size_t n) {
369 int result = wmemcmp(a, b, n);
370 if (result != 0)
371 clang_analyzer_eval(n != 0); // expected-warning{{TRUE}}
372 // else
373 // analyzer_assert_unknown(n == 0);
375 // We can't do the above comparison because n has already been constrained.
376 // On one path n == 0, on the other n != 0.
379 int wmemcmp7 (wchar_t *a, size_t x, size_t y, size_t n) {
380 // We used to crash when either of the arguments was unknown.
381 return wmemcmp(a, &a[x*y], n) +
382 wmemcmp(&a[x*y], a, n);
385 int wmemcmp8(wchar_t *a, size_t n) {
386 wchar_t *b = 0;
387 // Do not warn about the first argument!
388 return wmemcmp(a, b, n); // expected-warning{{Null pointer passed as 2nd argument to memory comparison function}}
391 //===----------------------------------------------------------------------===
392 // wcslen()
393 //===----------------------------------------------------------------------===
395 #define wcslen BUILTIN(wcslen)
396 size_t wcslen(const wchar_t *s);
398 void wcslen_constant0(void) {
399 clang_analyzer_eval(wcslen(L"123") == 3); // expected-warning{{TRUE}}
402 void wcslen_constant1(void) {
403 const wchar_t *a = L"123";
404 clang_analyzer_eval(wcslen(a) == 3); // expected-warning{{TRUE}}
407 void wcslen_constant2(wchar_t x) {
408 wchar_t a[] = L"123";
409 clang_analyzer_eval(wcslen(a) == 3); // expected-warning{{TRUE}}
411 a[0] = x;
412 clang_analyzer_eval(wcslen(a) == 3); // expected-warning{{UNKNOWN}}
415 size_t wcslen_null(void) {
416 return wcslen(0); // expected-warning{{Null pointer passed as 1st argument to string length function}}
419 size_t wcslen_fn(void) {
420 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}}
423 size_t wcslen_nonloc(void) {
424 label:
425 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}}
428 void wcslen_subregion(void) {
429 struct two_strings { wchar_t a[2], b[2]; };
430 extern void use_two_strings(struct two_strings *);
432 struct two_strings z;
433 use_two_strings(&z);
435 size_t a = wcslen(z.a);
436 z.b[0] = 5;
437 size_t b = wcslen(z.a);
438 if (a == 0)
439 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
441 use_two_strings(&z);
443 size_t c = wcslen(z.a);
444 if (a == 0)
445 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
448 extern void use_string(wchar_t *);
449 void wcslen_argument(wchar_t *x) {
450 size_t a = wcslen(x);
451 size_t b = wcslen(x);
452 if (a == 0)
453 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
455 use_string(x);
457 size_t c = wcslen(x);
458 if (a == 0)
459 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
462 extern wchar_t global_str[];
463 void wcslen_global(void) {
464 size_t a = wcslen(global_str);
465 size_t b = wcslen(global_str);
466 if (a == 0) {
467 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
468 // Make sure clang_analyzer_eval does not invalidate globals.
469 clang_analyzer_eval(wcslen(global_str) == 0); // expected-warning{{TRUE}}
472 // Call a function with unknown effects, which should invalidate globals.
473 use_string(0);
475 size_t c = wcslen(global_str);
476 if (a == 0)
477 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
480 void wcslen_indirect(wchar_t *x) {
481 size_t a = wcslen(x);
482 wchar_t *p = x;
483 wchar_t **p2 = &p;
484 size_t b = wcslen(x);
485 if (a == 0)
486 clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
488 extern void use_string_ptr(wchar_t*const*);
489 use_string_ptr(p2);
491 size_t c = wcslen(x);
492 if (a == 0)
493 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
496 void wcslen_indirect2(wchar_t *x) {
497 size_t a = wcslen(x);
498 wchar_t *p = x;
499 wchar_t **p2 = &p;
500 extern void use_string_ptr2(wchar_t**);
501 use_string_ptr2(p2);
503 size_t c = wcslen(x);
504 if (a == 0)
505 clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
508 void wcslen_liveness(const wchar_t *x) {
509 if (wcslen(x) < 5)
510 return;
511 clang_analyzer_eval(wcslen(x) < 5); // expected-warning{{FALSE}}
515 size_t wcslenWrapper(const wchar_t *str) {
516 return wcslen(str);
519 extern void invalidate(wchar_t *s);
521 void testwcslenCallee(void) {
522 wchar_t str[42];
523 invalidate(str);
524 size_t lenBefore = wcslenWrapper(str);
525 invalidate(str);
526 size_t lenAfter = wcslenWrapper(str);
527 clang_analyzer_eval(lenBefore == lenAfter); // expected-warning{{UNKNOWN}}
530 //===----------------------------------------------------------------------===
531 // wcsnlen()
532 //===----------------------------------------------------------------------===
534 size_t wcsnlen(const wchar_t *s, size_t maxlen);
536 void wcsnlen_constant0(void) {
537 clang_analyzer_eval(wcsnlen(L"123", 10) == 3); // expected-warning{{TRUE}}
540 void wcsnlen_constant1(void) {
541 const wchar_t *a = L"123";
542 clang_analyzer_eval(wcsnlen(a, 10) == 3); // expected-warning{{TRUE}}
545 void wcsnlen_constant2(char x) {
546 wchar_t a[] = L"123";
547 clang_analyzer_eval(wcsnlen(a, 10) == 3); // expected-warning{{TRUE}}
548 a[0] = x;
549 clang_analyzer_eval(wcsnlen(a, 10) == 3); // expected-warning{{UNKNOWN}}
552 void wcsnlen_constant4(void) {
553 clang_analyzer_eval(wcsnlen(L"123456", 3) == 3); // expected-warning{{TRUE}}
556 void wcsnlen_constant5(void) {
557 const wchar_t *a = L"123456";
558 clang_analyzer_eval(wcsnlen(a, 3) == 3); // expected-warning{{TRUE}}
561 void wcsnlen_constant6(char x) {
562 wchar_t a[] = L"123456";
563 clang_analyzer_eval(wcsnlen(a, 3) == 3); // expected-warning{{TRUE}}
564 a[0] = x;
565 clang_analyzer_eval(wcsnlen(a, 3) == 3); // expected-warning{{UNKNOWN}}
568 size_t wcsnlen_null(void) {
569 return wcsnlen(0, 3); // expected-warning{{Null pointer passed as 1st argument to string length function}}
572 size_t wcsnlen_fn(void) {
573 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}}
576 size_t wcsnlen_nonloc(void) {
577 label:
578 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}}
581 void wcsnlen_zero(void) {
582 clang_analyzer_eval(wcsnlen(L"abc", 0) == 0); // expected-warning{{TRUE}}
583 clang_analyzer_eval(wcsnlen(0, 0) == 0); // expected-warning{{TRUE}}
586 size_t wcsnlen_compound_literal(void) {
587 // This used to crash because we don't model the string lengths of
588 // compound literals.
589 return wcsnlen((wchar_t[]) { 'a', 'b', 0 }, 1);
592 size_t wcsnlen_unknown_limit(float f) {
593 // This used to crash because we don't model the integer values of floats.
594 return wcsnlen(L"abc", (int)f);
597 void wcsnlen_is_not_wcslen(wchar_t *x) {
598 clang_analyzer_eval(wcsnlen(x, 10) == wcslen(x)); // expected-warning{{UNKNOWN}}
601 void wcsnlen_at_limit(wchar_t *x) {
602 size_t len = wcsnlen(x, 10);
603 clang_analyzer_eval(len <= 10); // expected-warning{{TRUE}}
604 clang_analyzer_eval(len == 10); // expected-warning{{UNKNOWN}}
605 clang_analyzer_eval(len < 10); // expected-warning{{UNKNOWN}}
608 void wcsnlen_at_actual(size_t limit) {
609 size_t len = wcsnlen(L"abc", limit);
610 clang_analyzer_eval(len <= 3); // expected-warning{{TRUE}}
611 // This is due to eager assertion in wcsnlen.
612 if (limit == 0) {
613 clang_analyzer_eval(len == 0); // expected-warning{{TRUE}}
614 } else {
615 clang_analyzer_eval(len == 3); // expected-warning{{UNKNOWN}}
616 clang_analyzer_eval(len < 3); // expected-warning{{UNKNOWN}}
620 //===----------------------------------------------------------------------===
621 // other tests
622 //===----------------------------------------------------------------------===
624 static const wchar_t w_str[] = L"Hello world";
626 void wmemcpy_sizeof(void) {
627 wchar_t a[32];
628 wmemcpy(a, w_str, sizeof(w_str) / sizeof(w_str[0]));
629 wmemcpy(a, w_str, (sizeof(w_str) / sizeof(w_str[0])) + 1); // expected-warning {{Memory copy function accesses out-of-bound array element}}
632 void wmemcpy_wcslen(void) {
633 wchar_t a[32];
634 // FIXME: This should work with 'w_str' instead of 'w_str1'
635 const wchar_t w_str1[] = L"Hello world";
636 wmemcpy(a, w_str1, wcslen(w_str1) + 1);
637 wmemcpy(a, w_str1, wcslen(w_str1) + 2); // expected-warning {{Memory copy function accesses out-of-bound array element}}