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