1 // Check the basic reporting/warning and the application of constraints.
2 // RUN: %clang_analyze_cc1 %s \
3 // RUN: -analyzer-checker=core \
4 // RUN: -analyzer-checker=apiModeling.StdCLibraryFunctions \
5 // RUN: -analyzer-checker=alpha.unix.StdCLibraryFunctionArgs \
6 // RUN: -analyzer-checker=debug.StdCLibraryFunctionsTester \
7 // RUN: -analyzer-checker=debug.ExprInspection \
8 // RUN: -triple x86_64-unknown-linux-gnu \
9 // RUN: -verify=report
10
11 // Check the bugpath related to the reports.
12 // RUN: %clang_analyze_cc1 %s \
13 // RUN: -analyzer-checker=core \
14 // RUN: -analyzer-checker=apiModeling.StdCLibraryFunctions \
15 // RUN: -analyzer-checker=alpha.unix.StdCLibraryFunctionArgs \
16 // RUN: -analyzer-checker=debug.StdCLibraryFunctionsTester \
17 // RUN: -analyzer-checker=debug.ExprInspection \
18 // RUN: -triple x86_64-unknown-linux-gnu \
19 // RUN: -analyzer-output=text \
20 // RUN: -verify=bugpath
21
22 void clang_analyzer_eval(int);
23
24 int glob;
25
26 #define EOF -1
27
28 int isalnum(int);
29
test_alnum_concrete(int v)30 void test_alnum_concrete(int v) {
31 int ret = isalnum(256); // \
32 // report-warning{{Function argument constraint is not satisfied}} \
33 // report-note{{}} \
34 // bugpath-warning{{Function argument constraint is not satisfied}} \
35 // bugpath-note{{}} \
36 // bugpath-note{{Function argument constraint is not satisfied}}
37 (void)ret;
38 }
39
test_alnum_symbolic(int x)40 void test_alnum_symbolic(int x) {
41 int ret = isalnum(x);
42 (void)ret;
43
44 clang_analyzer_eval(EOF <= x && x <= 255); // \
45 // report-warning{{TRUE}} \
46 // bugpath-warning{{TRUE}} \
47 // bugpath-note{{TRUE}} \
48 // bugpath-note{{Left side of '&&' is true}} \
49 // bugpath-note{{'x' is <= 255}}
50 }
51
test_alnum_symbolic2(int x)52 void test_alnum_symbolic2(int x) {
53 if (x > 255) { // \
54 // bugpath-note{{Assuming 'x' is > 255}} \
55 // bugpath-note{{Taking true branch}}
56
57 int ret = isalnum(x); // \
58 // report-warning{{Function argument constraint is not satisfied}} \
59 // report-note{{}} \
60 // bugpath-warning{{Function argument constraint is not satisfied}} \
61 // bugpath-note{{}} \
62 // bugpath-note{{Function argument constraint is not satisfied}}
63
64 (void)ret;
65 }
66 }
67
68 int toupper(int);
69
test_toupper_concrete(int v)70 void test_toupper_concrete(int v) {
71 int ret = toupper(256); // \
72 // report-warning{{Function argument constraint is not satisfied}} \
73 // report-note{{}} \
74 // bugpath-warning{{Function argument constraint is not satisfied}} \
75 // bugpath-note{{}} \
76 // bugpath-note{{Function argument constraint is not satisfied}}
77 (void)ret;
78 }
79
test_toupper_symbolic(int x)80 void test_toupper_symbolic(int x) {
81 int ret = toupper(x);
82 (void)ret;
83
84 clang_analyzer_eval(EOF <= x && x <= 255); // \
85 // report-warning{{TRUE}} \
86 // bugpath-warning{{TRUE}} \
87 // bugpath-note{{TRUE}} \
88 // bugpath-note{{Left side of '&&' is true}} \
89 // bugpath-note{{'x' is <= 255}}
90 }
91
test_toupper_symbolic2(int x)92 void test_toupper_symbolic2(int x) {
93 if (x > 255) { // \
94 // bugpath-note{{Assuming 'x' is > 255}} \
95 // bugpath-note{{Taking true branch}}
96
97 int ret = toupper(x); // \
98 // report-warning{{Function argument constraint is not satisfied}} \
99 // report-note{{}} \
100 // bugpath-warning{{Function argument constraint is not satisfied}} \
101 // bugpath-note{{}} \
102 // bugpath-note{{Function argument constraint is not satisfied}}
103
104 (void)ret;
105 }
106 }
107
108 int tolower(int);
109
test_tolower_concrete(int v)110 void test_tolower_concrete(int v) {
111 int ret = tolower(256); // \
112 // report-warning{{Function argument constraint is not satisfied}} \
113 // report-note{{}} \
114 // bugpath-warning{{Function argument constraint is not satisfied}} \
115 // bugpath-note{{}} \
116 // bugpath-note{{Function argument constraint is not satisfied}}
117 (void)ret;
118 }
119
test_tolower_symbolic(int x)120 void test_tolower_symbolic(int x) {
121 int ret = tolower(x);
122 (void)ret;
123
124 clang_analyzer_eval(EOF <= x && x <= 255); // \
125 // report-warning{{TRUE}} \
126 // bugpath-warning{{TRUE}} \
127 // bugpath-note{{TRUE}} \
128 // bugpath-note{{Left side of '&&' is true}} \
129 // bugpath-note{{'x' is <= 255}}
130 }
131
test_tolower_symbolic2(int x)132 void test_tolower_symbolic2(int x) {
133 if (x > 255) { // \
134 // bugpath-note{{Assuming 'x' is > 255}} \
135 // bugpath-note{{Taking true branch}}
136
137 int ret = tolower(x); // \
138 // report-warning{{Function argument constraint is not satisfied}} \
139 // report-note{{}} \
140 // bugpath-warning{{Function argument constraint is not satisfied}} \
141 // bugpath-note{{}} \
142 // bugpath-note{{Function argument constraint is not satisfied}}
143
144 (void)ret;
145 }
146 }
147
148 int toascii(int);
149
test_toascii_concrete(int v)150 void test_toascii_concrete(int v) {
151 int ret = toascii(256); // \
152 // report-warning{{Function argument constraint is not satisfied}} \
153 // report-note{{}} \
154 // bugpath-warning{{Function argument constraint is not satisfied}} \
155 // bugpath-note{{}} \
156 // bugpath-note{{Function argument constraint is not satisfied}}
157 (void)ret;
158 }
159
test_toascii_symbolic(int x)160 void test_toascii_symbolic(int x) {
161 int ret = toascii(x);
162 (void)ret;
163
164 clang_analyzer_eval(EOF <= x && x <= 255); // \
165 // report-warning{{TRUE}} \
166 // bugpath-warning{{TRUE}} \
167 // bugpath-note{{TRUE}} \
168 // bugpath-note{{Left side of '&&' is true}} \
169 // bugpath-note{{'x' is <= 255}}
170 }
171
test_toascii_symbolic2(int x)172 void test_toascii_symbolic2(int x) {
173 if (x > 255) { // \
174 // bugpath-note{{Assuming 'x' is > 255}} \
175 // bugpath-note{{Taking true branch}}
176
177 int ret = toascii(x); // \
178 // report-warning{{Function argument constraint is not satisfied}} \
179 // report-note{{}} \
180 // bugpath-warning{{Function argument constraint is not satisfied}} \
181 // bugpath-note{{}} \
182 // bugpath-note{{Function argument constraint is not satisfied}}
183
184 (void)ret;
185 }
186 }
187
188 typedef struct FILE FILE;
189 typedef typeof(sizeof(int)) size_t;
190 size_t fread(void *restrict, size_t, size_t, FILE *restrict);
test_notnull_concrete(FILE * fp)191 void test_notnull_concrete(FILE *fp) {
192 fread(0, sizeof(int), 10, fp); // \
193 // report-warning{{Function argument constraint is not satisfied}} \
194 // report-note{{}} \
195 // bugpath-warning{{Function argument constraint is not satisfied}} \
196 // bugpath-note{{}} \
197 // bugpath-note{{Function argument constraint is not satisfied}}
198 }
test_notnull_symbolic(FILE * fp,int * buf)199 void test_notnull_symbolic(FILE *fp, int *buf) {
200 fread(buf, sizeof(int), 10, fp);
201 clang_analyzer_eval(buf != 0); // \
202 // report-warning{{TRUE}} \
203 // bugpath-warning{{TRUE}} \
204 // bugpath-note{{TRUE}} \
205 // bugpath-note{{'buf' is not equal to null}}
206 }
test_notnull_symbolic2(FILE * fp,int * buf)207 void test_notnull_symbolic2(FILE *fp, int *buf) {
208 if (!buf) // bugpath-note{{Assuming 'buf' is null}} \
209 // bugpath-note{{Taking true branch}}
210 fread(buf, sizeof(int), 10, fp); // \
211 // report-warning{{Function argument constraint is not satisfied}} \
212 // report-note{{}} \
213 // bugpath-warning{{Function argument constraint is not satisfied}} \
214 // bugpath-note{{}} \
215 // bugpath-note{{Function argument constraint is not satisfied}}
216 }
217 typedef __WCHAR_TYPE__ wchar_t;
218 // This is one test case for the ARR38-C SEI-CERT rule.
ARR38_C_F(FILE * file)219 void ARR38_C_F(FILE *file) {
220 enum { BUFFER_SIZE = 1024 };
221 wchar_t wbuf[BUFFER_SIZE]; // bugpath-note{{'wbuf' initialized here}}
222
223 const size_t size = sizeof(*wbuf); // bugpath-note{{'size' initialized to}}
224 const size_t nitems = sizeof(wbuf); // bugpath-note{{'nitems' initialized to}}
225
226 // The 3rd parameter should be the number of elements to read, not
227 // the size in bytes.
228 fread(wbuf, size, nitems, file); // \
229 // report-warning{{Function argument constraint is not satisfied}} \
230 // report-note{{}} \
231 // bugpath-warning{{Function argument constraint is not satisfied}} \
232 // bugpath-note{{}} \
233 // bugpath-note{{Function argument constraint is not satisfied}}
234 }
235
236 int __two_constrained_args(int, int);
test_constraints_on_multiple_args(int x,int y)237 void test_constraints_on_multiple_args(int x, int y) {
238 // State split should not happen here. I.e. x == 1 should not be evaluated
239 // FALSE.
240 __two_constrained_args(x, y);
241 clang_analyzer_eval(x == 1); // \
242 // report-warning{{TRUE}} \
243 // bugpath-warning{{TRUE}} \
244 // bugpath-note{{TRUE}}
245 clang_analyzer_eval(y == 1); // \
246 // report-warning{{TRUE}} \
247 // bugpath-warning{{TRUE}} \
248 // bugpath-note{{TRUE}}
249 }
250
251 int __arg_constrained_twice(int);
test_multiple_constraints_on_same_arg(int x)252 void test_multiple_constraints_on_same_arg(int x) {
253 __arg_constrained_twice(x);
254 // Check that both constraints are applied and only one branch is there.
255 clang_analyzer_eval(x < 1 || x > 2); // \
256 // report-warning{{TRUE}} \
257 // bugpath-warning{{TRUE}} \
258 // bugpath-note{{TRUE}} \
259 // bugpath-note{{Assuming 'x' is < 1}} \
260 // bugpath-note{{Left side of '||' is true}}
261 }
262
263 int __variadic(void *stream, const char *format, ...);
test_arg_constraint_on_variadic_fun()264 void test_arg_constraint_on_variadic_fun() {
265 __variadic(0, "%d%d", 1, 2); // \
266 // report-warning{{Function argument constraint is not satisfied}} \
267 // report-note{{}} \
268 // bugpath-warning{{Function argument constraint is not satisfied}} \
269 // bugpath-note{{}} \
270 // bugpath-note{{Function argument constraint is not satisfied}}
271 }
272
273 int __buf_size_arg_constraint(const void *, size_t);
test_buf_size_concrete()274 void test_buf_size_concrete() {
275 char buf[3]; // bugpath-note{{'buf' initialized here}}
276 __buf_size_arg_constraint(buf, 4); // \
277 // report-warning{{Function argument constraint is not satisfied}} \
278 // report-note{{}} \
279 // bugpath-warning{{Function argument constraint is not satisfied}} \
280 // bugpath-note{{}} \
281 // bugpath-note{{Function argument constraint is not satisfied}}
282 }
test_buf_size_symbolic(int s)283 void test_buf_size_symbolic(int s) {
284 char buf[3];
285 __buf_size_arg_constraint(buf, s);
286 clang_analyzer_eval(s <= 3); // \
287 // report-warning{{TRUE}} \
288 // bugpath-warning{{TRUE}} \
289 // bugpath-note{{TRUE}} \
290 // bugpath-note{{'s' is <= 3}}
291 }
test_buf_size_symbolic_and_offset(int s)292 void test_buf_size_symbolic_and_offset(int s) {
293 char buf[3];
294 __buf_size_arg_constraint(buf + 1, s);
295 clang_analyzer_eval(s <= 2); // \
296 // report-warning{{TRUE}} \
297 // bugpath-warning{{TRUE}} \
298 // bugpath-note{{TRUE}} \
299 // bugpath-note{{'s' is <= 2}}
300 }
301
302 int __buf_size_arg_constraint_mul(const void *, size_t, size_t);
test_buf_size_concrete_with_multiplication()303 void test_buf_size_concrete_with_multiplication() {
304 short buf[3]; // bugpath-note{{'buf' initialized here}}
305 __buf_size_arg_constraint_mul(buf, 4, sizeof(short)); // \
306 // report-warning{{Function argument constraint is not satisfied}} \
307 // report-note{{}} \
308 // bugpath-warning{{Function argument constraint is not satisfied}} \
309 // bugpath-note{{}} \
310 // bugpath-note{{Function argument constraint is not satisfied}}
311 }
test_buf_size_symbolic_with_multiplication(size_t s)312 void test_buf_size_symbolic_with_multiplication(size_t s) {
313 short buf[3];
314 __buf_size_arg_constraint_mul(buf, s, sizeof(short));
315 clang_analyzer_eval(s * sizeof(short) <= 6); // \
316 // report-warning{{TRUE}} \
317 // bugpath-warning{{TRUE}} \
318 // bugpath-note{{TRUE}}
319 }
test_buf_size_symbolic_and_offset_with_multiplication(size_t s)320 void test_buf_size_symbolic_and_offset_with_multiplication(size_t s) {
321 short buf[3];
322 __buf_size_arg_constraint_mul(buf + 1, s, sizeof(short));
323 clang_analyzer_eval(s * sizeof(short) <= 4); // \
324 // report-warning{{TRUE}} \
325 // bugpath-warning{{TRUE}} \
326 // bugpath-note{{TRUE}}
327 }
328
329 // The minimum buffer size for this function is set to 10.
330 int __buf_size_arg_constraint_concrete(const void *);
test_min_buf_size()331 void test_min_buf_size() {
332 char buf[9];// bugpath-note{{'buf' initialized here}}
333 __buf_size_arg_constraint_concrete(buf); // \
334 // report-warning{{Function argument constraint is not satisfied}} \
335 // report-note{{}} \
336 // bugpath-warning{{Function argument constraint is not satisfied}} \
337 // bugpath-note{{}} \
338 // bugpath-note{{Function argument constraint is not satisfied}}
339 }
340