xref: /minix3/external/bsd/llvm/dist/clang/test/Analysis/bstring.c (revision 0b98e8aad89f2bd4ba80b523d73cf29e9dd82ce1)
1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
2 // RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
3 // RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
4 // RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
5 
6 //===----------------------------------------------------------------------===
7 // Declarations
8 //===----------------------------------------------------------------------===
9 
10 // Some functions are so similar to each other that they follow the same code
11 // path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is
12 // defined, make sure to use the variants instead to make sure they are still
13 // checked by the analyzer.
14 
15 // Some functions are implemented as builtins. These should be #defined as
16 // BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.
17 
18 // Functions that have variants and are also available as builtins should be
19 // declared carefully! See memcpy() for an example.
20 
21 #ifdef USE_BUILTINS
22 # define BUILTIN(f) __builtin_ ## f
23 #else /* USE_BUILTINS */
24 # define BUILTIN(f) f
25 #endif /* USE_BUILTINS */
26 
27 typedef typeof(sizeof(int)) size_t;
28 
29 void clang_analyzer_eval(int);
30 
31 //===----------------------------------------------------------------------===
32 // memcpy()
33 //===----------------------------------------------------------------------===
34 
35 #ifdef VARIANT
36 
37 #define __memcpy_chk BUILTIN(__memcpy_chk)
38 void *__memcpy_chk(void *restrict s1, const void *restrict s2, size_t n,
39                    size_t destlen);
40 
41 #define memcpy(a,b,c) __memcpy_chk(a,b,c,(size_t)-1)
42 
43 #else /* VARIANT */
44 
45 #define memcpy BUILTIN(memcpy)
46 void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
47 
48 #endif /* VARIANT */
49 
50 
51 void memcpy0 () {
52   char src[] = {1, 2, 3, 4};
53   char dst[4] = {0};
54 
55   memcpy(dst, src, 4); // no-warning
56 
57   clang_analyzer_eval(memcpy(dst, src, 4) == dst); // expected-warning{{TRUE}}
58 
59   // If we actually model the copy, we can make this known.
60   // The important thing for now is that the old value has been invalidated.
61   clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
62 }
63 
64 void memcpy1 () {
65   char src[] = {1, 2, 3, 4};
66   char dst[10];
67 
68   memcpy(dst, src, 5); // expected-warning{{Memory copy function accesses out-of-bound array element}}
69 }
70 
71 void memcpy2 () {
72   char src[] = {1, 2, 3, 4};
73   char dst[1];
74 
75   memcpy(dst, src, 4); // expected-warning{{Memory copy function overflows destination buffer}}
76 }
77 
78 void memcpy3 () {
79   char src[] = {1, 2, 3, 4};
80   char dst[3];
81 
82   memcpy(dst+1, src+2, 2); // no-warning
83 }
84 
85 void memcpy4 () {
86   char src[] = {1, 2, 3, 4};
87   char dst[10];
88 
89   memcpy(dst+2, src+2, 3); // expected-warning{{Memory copy function accesses out-of-bound array element}}
90 }
91 
92 void memcpy5() {
93   char src[] = {1, 2, 3, 4};
94   char dst[3];
95 
96   memcpy(dst+2, src+2, 2); // expected-warning{{Memory copy function overflows destination buffer}}
97 }
98 
99 void memcpy6() {
100   int a[4] = {0};
101   memcpy(a, a, 8); // expected-warning{{overlapping}}
102 }
103 
104 void memcpy7() {
105   int a[4] = {0};
106   memcpy(a+2, a+1, 8); // expected-warning{{overlapping}}
107 }
108 
109 void memcpy8() {
110   int a[4] = {0};
111   memcpy(a+1, a+2, 8); // expected-warning{{overlapping}}
112 }
113 
114 void memcpy9() {
115   int a[4] = {0};
116   memcpy(a+2, a+1, 4); // no-warning
117   memcpy(a+1, a+2, 4); // no-warning
118 }
119 
120 void memcpy10() {
121   char a[4] = {0};
122   memcpy(0, a, 4); // expected-warning{{Null pointer argument in call to memory copy function}}
123 }
124 
125 void memcpy11() {
126   char a[4] = {0};
127   memcpy(a, 0, 4); // expected-warning{{Null pointer argument in call to memory copy function}}
128 }
129 
130 void memcpy12() {
131   char a[4] = {0};
132   memcpy(0, a, 0); // no-warning
133 }
134 
135 void memcpy13() {
136   char a[4] = {0};
137   memcpy(a, 0, 0); // no-warning
138 }
139 
140 void memcpy_unknown_size (size_t n) {
141   char a[4], b[4] = {1};
142   clang_analyzer_eval(memcpy(a, b, n) == a); // expected-warning{{TRUE}}
143 }
144 
145 void memcpy_unknown_size_warn (size_t n) {
146   char a[4];
147   void *result = memcpy(a, 0, n); // expected-warning{{Null pointer argument in call to memory copy function}}
148   clang_analyzer_eval(result == a); // no-warning (above is fatal)
149 }
150 
151 //===----------------------------------------------------------------------===
152 // mempcpy()
153 //===----------------------------------------------------------------------===
154 
155 #ifdef VARIANT
156 
157 #define __mempcpy_chk BUILTIN(__mempcpy_chk)
158 void *__mempcpy_chk(void *restrict s1, const void *restrict s2, size_t n,
159                    size_t destlen);
160 
161 #define mempcpy(a,b,c) __mempcpy_chk(a,b,c,(size_t)-1)
162 
163 #else /* VARIANT */
164 
165 #define mempcpy BUILTIN(mempcpy)
166 void *mempcpy(void *restrict s1, const void *restrict s2, size_t n);
167 
168 #endif /* VARIANT */
169 
170 
171 void mempcpy0 () {
172   char src[] = {1, 2, 3, 4};
173   char dst[5] = {0};
174 
175   mempcpy(dst, src, 4); // no-warning
176 
177   clang_analyzer_eval(mempcpy(dst, src, 4) == &dst[4]); // expected-warning{{TRUE}}
178 
179   // If we actually model the copy, we can make this known.
180   // The important thing for now is that the old value has been invalidated.
181   clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
182 }
183 
184 void mempcpy1 () {
185   char src[] = {1, 2, 3, 4};
186   char dst[10];
187 
188   mempcpy(dst, src, 5); // expected-warning{{Memory copy function accesses out-of-bound array element}}
189 }
190 
191 void mempcpy2 () {
192   char src[] = {1, 2, 3, 4};
193   char dst[1];
194 
195   mempcpy(dst, src, 4); // expected-warning{{Memory copy function overflows destination buffer}}
196 }
197 
198 void mempcpy3 () {
199   char src[] = {1, 2, 3, 4};
200   char dst[3];
201 
202   mempcpy(dst+1, src+2, 2); // no-warning
203 }
204 
205 void mempcpy4 () {
206   char src[] = {1, 2, 3, 4};
207   char dst[10];
208 
209   mempcpy(dst+2, src+2, 3); // expected-warning{{Memory copy function accesses out-of-bound array element}}
210 }
211 
212 void mempcpy5() {
213   char src[] = {1, 2, 3, 4};
214   char dst[3];
215 
216   mempcpy(dst+2, src+2, 2); // expected-warning{{Memory copy function overflows destination buffer}}
217 }
218 
219 void mempcpy6() {
220   int a[4] = {0};
221   mempcpy(a, a, 8); // expected-warning{{overlapping}}
222 }
223 
224 void mempcpy7() {
225   int a[4] = {0};
226   mempcpy(a+2, a+1, 8); // expected-warning{{overlapping}}
227 }
228 
229 void mempcpy8() {
230   int a[4] = {0};
231   mempcpy(a+1, a+2, 8); // expected-warning{{overlapping}}
232 }
233 
234 void mempcpy9() {
235   int a[4] = {0};
236   mempcpy(a+2, a+1, 4); // no-warning
237   mempcpy(a+1, a+2, 4); // no-warning
238 }
239 
240 void mempcpy10() {
241   char a[4] = {0};
242   mempcpy(0, a, 4); // expected-warning{{Null pointer argument in call to memory copy function}}
243 }
244 
245 void mempcpy11() {
246   char a[4] = {0};
247   mempcpy(a, 0, 4); // expected-warning{{Null pointer argument in call to memory copy function}}
248 }
249 
250 void mempcpy12() {
251   char a[4] = {0};
252   mempcpy(0, a, 0); // no-warning
253 }
254 
255 void mempcpy13() {
256   char a[4] = {0};
257   mempcpy(a, 0, 0); // no-warning
258 }
259 
260 void mempcpy_unknown_size_warn (size_t n) {
261   char a[4];
262   void *result = mempcpy(a, 0, n); // expected-warning{{Null pointer argument in call to memory copy function}}
263   clang_analyzer_eval(result == a); // no-warning (above is fatal)
264 }
265 
266 void mempcpy_unknownable_size (char *src, float n) {
267   char a[4];
268   // This used to crash because we don't model floats.
269   mempcpy(a, src, (size_t)n);
270 }
271 
272 //===----------------------------------------------------------------------===
273 // memmove()
274 //===----------------------------------------------------------------------===
275 
276 #ifdef VARIANT
277 
278 #define __memmove_chk BUILTIN(__memmove_chk)
279 void *__memmove_chk(void *s1, const void *s2, size_t n, size_t destlen);
280 
281 #define memmove(a,b,c) __memmove_chk(a,b,c,(size_t)-1)
282 
283 #else /* VARIANT */
284 
285 #define memmove BUILTIN(memmove)
286 void *memmove(void *s1, const void *s2, size_t n);
287 
288 #endif /* VARIANT */
289 
290 
291 void memmove0 () {
292   char src[] = {1, 2, 3, 4};
293   char dst[4] = {0};
294 
295   memmove(dst, src, 4); // no-warning
296 
297   clang_analyzer_eval(memmove(dst, src, 4) == dst); // expected-warning{{TRUE}}
298 
299   // If we actually model the copy, we can make this known.
300   // The important thing for now is that the old value has been invalidated.
301   clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
302 }
303 
304 void memmove1 () {
305   char src[] = {1, 2, 3, 4};
306   char dst[10];
307 
308   memmove(dst, src, 5); // expected-warning{{out-of-bound}}
309 }
310 
311 void memmove2 () {
312   char src[] = {1, 2, 3, 4};
313   char dst[1];
314 
315   memmove(dst, src, 4); // expected-warning{{overflow}}
316 }
317 
318 //===----------------------------------------------------------------------===
319 // memcmp()
320 //===----------------------------------------------------------------------===
321 
322 #ifdef VARIANT
323 
324 #define bcmp BUILTIN(bcmp)
325 // __builtin_bcmp is not defined with const in Builtins.def.
326 int bcmp(/*const*/ void *s1, /*const*/ void *s2, size_t n);
327 #define memcmp bcmp
328 //
329 #else /* VARIANT */
330 
331 #define memcmp BUILTIN(memcmp)
332 int memcmp(const void *s1, const void *s2, size_t n);
333 
334 #endif /* VARIANT */
335 
336 
337 void memcmp0 () {
338   char a[] = {1, 2, 3, 4};
339   char b[4] = { 0 };
340 
341   memcmp(a, b, 4); // no-warning
342 }
343 
344 void memcmp1 () {
345   char a[] = {1, 2, 3, 4};
346   char b[10] = { 0 };
347 
348   memcmp(a, b, 5); // expected-warning{{out-of-bound}}
349 }
350 
351 void memcmp2 () {
352   char a[] = {1, 2, 3, 4};
353   char b[1] = { 0 };
354 
355   memcmp(a, b, 4); // expected-warning{{out-of-bound}}
356 }
357 
358 void memcmp3 () {
359   char a[] = {1, 2, 3, 4};
360 
361   clang_analyzer_eval(memcmp(a, a, 4) == 0); // expected-warning{{TRUE}}
362 }
363 
364 void memcmp4 (char *input) {
365   char a[] = {1, 2, 3, 4};
366 
367   clang_analyzer_eval(memcmp(a, input, 4) == 0); // expected-warning{{UNKNOWN}}
368 }
369 
370 void memcmp5 (char *input) {
371   char a[] = {1, 2, 3, 4};
372 
373   clang_analyzer_eval(memcmp(a, 0, 0) == 0); // expected-warning{{TRUE}}
374   clang_analyzer_eval(memcmp(0, a, 0) == 0); // expected-warning{{TRUE}}
375   clang_analyzer_eval(memcmp(a, input, 0) == 0); // expected-warning{{TRUE}}
376 }
377 
378 void memcmp6 (char *a, char *b, size_t n) {
379   int result = memcmp(a, b, n);
380   if (result != 0)
381     clang_analyzer_eval(n != 0); // expected-warning{{TRUE}}
382   // else
383   //   analyzer_assert_unknown(n == 0);
384 
385   // We can't do the above comparison because n has already been constrained.
386   // On one path n == 0, on the other n != 0.
387 }
388 
389 int memcmp7 (char *a, size_t x, size_t y, size_t n) {
390   // We used to crash when either of the arguments was unknown.
391   return memcmp(a, &a[x*y], n) +
392          memcmp(&a[x*y], a, n);
393 }
394 
395 //===----------------------------------------------------------------------===
396 // bcopy()
397 //===----------------------------------------------------------------------===
398 
399 #define bcopy BUILTIN(bcopy)
400 // __builtin_bcopy is not defined with const in Builtins.def.
401 void bcopy(/*const*/ void *s1, void *s2, size_t n);
402 
403 
404 void bcopy0 () {
405   char src[] = {1, 2, 3, 4};
406   char dst[4] = {0};
407 
408   bcopy(src, dst, 4); // no-warning
409 
410   // If we actually model the copy, we can make this known.
411   // The important thing for now is that the old value has been invalidated.
412   clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
413 }
414 
415 void bcopy1 () {
416   char src[] = {1, 2, 3, 4};
417   char dst[10];
418 
419   bcopy(src, dst, 5); // expected-warning{{out-of-bound}}
420 }
421 
422 void bcopy2 () {
423   char src[] = {1, 2, 3, 4};
424   char dst[1];
425 
426   bcopy(src, dst, 4); // expected-warning{{overflow}}
427 }
428 
429 void *malloc(size_t);
430 void free(void *);
431 char radar_11125445_memcopythenlogfirstbyte(const char *input, size_t length) {
432   char *bytes = malloc(sizeof(char) * (length + 1));
433   memcpy(bytes, input, length);
434   char x = bytes[0]; // no warning
435   free(bytes);
436   return x;
437 }
438