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