1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s |
2 | // RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s |
3 | // XFAIL: * |
4 | |
5 | // This file is for tests that may eventually go into string.c, or may be |
6 | // deleted outright. At one point these tests passed, but only because we |
7 | // weren't correctly modelling the behavior of the relevant string functions. |
8 | // The tests aren't incorrect, but require the analyzer to be smarter about |
9 | // conjured values than it currently is. |
10 | |
11 | //===----------------------------------------------------------------------=== |
12 | // Declarations |
13 | //===----------------------------------------------------------------------=== |
14 | |
15 | // Some functions are so similar to each other that they follow the same code |
16 | // path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is |
17 | // defined, make sure to use the variants instead to make sure they are still |
18 | // checked by the analyzer. |
19 | |
20 | // Some functions are implemented as builtins. These should be #defined as |
21 | // BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined. |
22 | |
23 | // Functions that have variants and are also available as builtins should be |
24 | // declared carefully! See memcpy() for an example. |
25 | |
26 | #ifdef USE_BUILTINS |
27 | # define BUILTIN(f) __builtin_ ## f |
28 | #else /* USE_BUILTINS */ |
29 | # define BUILTIN(f) f |
30 | #endif /* USE_BUILTINS */ |
31 | |
32 | #define NULL 0 |
33 | typedef typeof(sizeof(int)) size_t; |
34 | |
35 | void clang_analyzer_eval(int); |
36 | |
37 | //===----------------------------------------------------------------------=== |
38 | // strnlen() |
39 | //===----------------------------------------------------------------------=== |
40 | |
41 | #define strnlen BUILTIN(strnlen) |
42 | size_t strnlen(const char *s, size_t maxlen); |
43 | |
44 | void strnlen_liveness(const char *x) { |
45 | if (strnlen(x, 10) < 5) |
46 | return; |
47 | clang_analyzer_eval(strnlen(x, 10) < 5); // expected-warning{{FALSE}} |
48 | } |
49 | |
50 | void strnlen_subregion() { |
51 | struct two_stringsn { char a[2], b[2]; }; |
52 | extern void use_two_stringsn(struct two_stringsn *); |
53 | |
54 | struct two_stringsn z; |
55 | use_two_stringsn(&z); |
56 | |
57 | size_t a = strnlen(z.a, 10); |
58 | z.b[0] = 5; |
59 | size_t b = strnlen(z.a, 10); |
60 | if (a == 0) |
61 | clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} |
62 | |
63 | use_two_stringsn(&z); |
64 | |
65 | size_t c = strnlen(z.a, 10); |
66 | if (a == 0) |
67 | clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} |
68 | } |
69 | |
70 | extern void use_stringn(char *); |
71 | void strnlen_argument(char *x) { |
72 | size_t a = strnlen(x, 10); |
73 | size_t b = strnlen(x, 10); |
74 | if (a == 0) |
75 | clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} |
76 | |
77 | use_stringn(x); |
78 | |
79 | size_t c = strnlen(x, 10); |
80 | if (a == 0) |
81 | clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} |
82 | } |
83 | |
84 | extern char global_strn[]; |
85 | void strnlen_global() { |
86 | size_t a = strnlen(global_strn, 10); |
87 | size_t b = strnlen(global_strn, 10); |
88 | if (a == 0) |
89 | clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} |
90 | |
91 | // Call a function with unknown effects, which should invalidate globals. |
92 | use_stringn(0); |
93 | |
94 | size_t c = strnlen(global_strn, 10); |
95 | if (a == 0) |
96 | clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} |
97 | } |
98 | |
99 | void strnlen_indirect(char *x) { |
100 | size_t a = strnlen(x, 10); |
101 | char *p = x; |
102 | char **p2 = &p; |
103 | size_t b = strnlen(x, 10); |
104 | if (a == 0) |
105 | clang_analyzer_eval(b == 0); // expected-warning{{TRUE}} |
106 | |
107 | extern void use_stringn_ptr(char*const*); |
108 | use_stringn_ptr(p2); |
109 | |
110 | size_t c = strnlen(x, 10); |
111 | if (a == 0) |
112 | clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}} |
113 | } |
114 | |