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
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 //===----------------------------------------------------------------------===
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.
25 # define BUILTIN(f) __builtin_ ## f
26 #else /* USE_BUILTINS */
28 #endif /* USE_BUILTINS */
30 typedef __SIZE_TYPE__
size_t;
31 typedef __WCHAR_TYPE__
wchar_t;
33 void clang_analyzer_eval(int);
35 //===----------------------------------------------------------------------===
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};
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};
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};
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};
73 wmemcpy(dst
+1, src
+2, 2); // no-warning
76 void wmemcpy4 (void) {
77 wchar_t src
[] = {1, 2, 3, 4};
80 wmemcpy(dst
+2, src
+2, 3); // expected-warning{{Memory copy function accesses out-of-bound array element}}
84 wchar_t src
[] = {1, 2, 3, 4};
87 wmemcpy(dst
+ 2, src
+ 2, 2); // expected-warning{{Memory copy function overflows the destination buffer}}
92 wmemcpy(a
, a
, 2); // expected-warning{{overlapping}}
97 wmemcpy(a
+2, a
+1, 2); // expected-warning{{overlapping}}
100 void wmemcpy8(void) {
102 wmemcpy(a
+1, a
+2, 2); // expected-warning{{overlapping}}
105 void wmemcpy9(void) {
107 wmemcpy(a
+2, a
+1, 1); // no-warning
108 wmemcpy(a
+1, a
+2, 1); // no-warning
111 void wmemcpy10(void) {
113 wmemcpy(0, a
, 1); // expected-warning{{Null pointer passed as 1st argument to memory copy function}}
116 void wmemcpy11(void) {
118 wmemcpy(a
, 0, 1); // expected-warning{{Null pointer passed as 2nd argument to memory copy function}}
121 void wmemcpy12(void) {
123 wmemcpy(0, a
, 0); // no-warning
126 void wmemcpy13(void) {
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
) {
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 //===----------------------------------------------------------------------===
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};
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};
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};
179 wmempcpy(dst
+1, src
+2, 2); // no-warning
182 void wmempcpy4 (void) {
183 wchar_t src
[] = {1, 2, 3, 4};
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};
193 wmempcpy(dst
+ 2, src
+ 2, 2); // expected-warning{{Memory copy function overflows the destination buffer}}
196 void wmempcpy6(void) {
198 wmempcpy(a
, a
, 2); // expected-warning{{overlapping}}
201 void wmempcpy7(void) {
203 wmempcpy(a
+2, a
+1, 2); // expected-warning{{overlapping}}
206 void wmempcpy8(void) {
208 wmempcpy(a
+1, a
+2, 2); // expected-warning{{overlapping}}
211 void wmempcpy9(void) {
213 wmempcpy(a
+2, a
+1, 1); // no-warning
214 wmempcpy(a
+1, a
+2, 1); // no-warning
217 void wmempcpy10(void) {
219 wmempcpy(0, a
, 1); // expected-warning{{Null pointer passed as 1st argument to memory copy function}}
222 void wmempcpy11(void) {
224 wmempcpy(a
, 0, 1); // expected-warning{{Null pointer passed as 2nd argument to memory copy function}}
227 void wmempcpy12(void) {
229 wmempcpy(0, a
, 0); // no-warning
232 void wmempcpy13(void) {
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};
242 p
= wmempcpy(dst
, src
, 4);
244 clang_analyzer_eval(p
== &dst
[4]); // expected-warning{{TRUE}}
252 void wmempcpy15(void) {
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}};
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
) {
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
) {
284 // This used to crash because we don't model floats.
285 wmempcpy(a
, src
, (size_t)n
);
288 //===----------------------------------------------------------------------===
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};
310 wmemmove(dst
, src
, 5); // expected-warning{{out-of-bound}}
313 void wmemmove2 (void) {
314 wchar_t src
[] = {1, 2, 3, 4};
317 wmemmove(dst
, src
, 4); // expected-warning{{Memory copy function overflows the destination buffer}}
320 //===----------------------------------------------------------------------===
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
);
371 clang_analyzer_eval(n
!= 0); // expected-warning{{TRUE}}
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
) {
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 //===----------------------------------------------------------------------===
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}}
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) {
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
;
435 size_t a
= wcslen(z
.a
);
437 size_t b
= wcslen(z
.a
);
439 clang_analyzer_eval(b
== 0); // expected-warning{{TRUE}}
443 size_t c
= wcslen(z
.a
);
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
);
453 clang_analyzer_eval(b
== 0); // expected-warning{{TRUE}}
457 size_t c
= wcslen(x
);
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
);
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.
475 size_t c
= wcslen(global_str
);
477 clang_analyzer_eval(c
== 0); // expected-warning{{UNKNOWN}}
480 void wcslen_indirect(wchar_t *x
) {
481 size_t a
= wcslen(x
);
484 size_t b
= wcslen(x
);
486 clang_analyzer_eval(b
== 0); // expected-warning{{TRUE}}
488 extern void use_string_ptr(wchar_t*const*);
491 size_t c
= wcslen(x
);
493 clang_analyzer_eval(c
== 0); // expected-warning{{UNKNOWN}}
496 void wcslen_indirect2(wchar_t *x
) {
497 size_t a
= wcslen(x
);
500 extern void use_string_ptr2(wchar_t**);
503 size_t c
= wcslen(x
);
505 clang_analyzer_eval(c
== 0); // expected-warning{{UNKNOWN}}
508 void wcslen_liveness(const wchar_t *x
) {
511 clang_analyzer_eval(wcslen(x
) < 5); // expected-warning{{FALSE}}
515 size_t wcslenWrapper(const wchar_t *str
) {
519 extern void invalidate(wchar_t *s
);
521 void testwcslenCallee(void) {
524 size_t lenBefore
= wcslenWrapper(str
);
526 size_t lenAfter
= wcslenWrapper(str
);
527 clang_analyzer_eval(lenBefore
== lenAfter
); // expected-warning{{UNKNOWN}}
530 //===----------------------------------------------------------------------===
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}}
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}}
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) {
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.
613 clang_analyzer_eval(len
== 0); // expected-warning{{TRUE}}
615 clang_analyzer_eval(len
== 3); // expected-warning{{UNKNOWN}}
616 clang_analyzer_eval(len
< 3); // expected-warning{{UNKNOWN}}
620 //===----------------------------------------------------------------------===
622 //===----------------------------------------------------------------------===
624 static const wchar_t w_str
[] = L
"Hello world";
626 void wmemcpy_sizeof(void) {
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) {
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}}