Clang Project

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