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