bstring.c revision 8a285ae6fc4926cc4e419025eec63e2d6696e13f
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.experimental.CString -analyzer-store=region -Wno-null-dereference -verify %s
2// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,cplusplus.experimental.CString -analyzer-store=region -Wno-null-dereference -verify %s
3// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,cplusplus.experimental.CString -analyzer-store=region -Wno-null-dereference -verify %s
4// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,cplusplus.experimental.CString -analyzer-store=region -Wno-null-dereference -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
27typedef typeof(sizeof(int)) size_t;
28
29//===----------------------------------------------------------------------===
30// memcpy()
31//===----------------------------------------------------------------------===
32
33#ifdef VARIANT
34
35#define __memcpy_chk BUILTIN(__memcpy_chk)
36void *__memcpy_chk(void *restrict s1, const void *restrict s2, size_t n,
37                   size_t destlen);
38
39#define memcpy(a,b,c) __memcpy_chk(a,b,c,(size_t)-1)
40
41#else /* VARIANT */
42
43#define memcpy BUILTIN(memcpy)
44void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
45
46#endif /* VARIANT */
47
48
49void memcpy0 () {
50  char src[] = {1, 2, 3, 4};
51  char dst[4] = {0};
52
53  memcpy(dst, src, 4); // no-warning
54
55  if (memcpy(dst, src, 4) != dst) {
56    (void)*(char*)0; // no-warning
57  }
58
59  if (dst[0] != 0)
60    (void)*(char*)0; // expected-warning{{null}}
61}
62
63void memcpy1 () {
64  char src[] = {1, 2, 3, 4};
65  char dst[10];
66
67  memcpy(dst, src, 5); // expected-warning{{Byte string function accesses out-of-bound array element}}
68}
69
70void memcpy2 () {
71  char src[] = {1, 2, 3, 4};
72  char dst[1];
73
74  memcpy(dst, src, 4); // expected-warning{{Byte string function overflows destination buffer}}
75}
76
77void memcpy3 () {
78  char src[] = {1, 2, 3, 4};
79  char dst[3];
80
81  memcpy(dst+1, src+2, 2); // no-warning
82}
83
84void memcpy4 () {
85  char src[] = {1, 2, 3, 4};
86  char dst[10];
87
88  memcpy(dst+2, src+2, 3); // expected-warning{{Byte string function accesses out-of-bound array element}}
89}
90
91void memcpy5() {
92  char src[] = {1, 2, 3, 4};
93  char dst[3];
94
95  memcpy(dst+2, src+2, 2); // expected-warning{{Byte string function overflows destination buffer}}
96}
97
98void memcpy6() {
99  int a[4] = {0};
100  memcpy(a, a, 8); // expected-warning{{overlapping}}
101}
102
103void memcpy7() {
104  int a[4] = {0};
105  memcpy(a+2, a+1, 8); // expected-warning{{overlapping}}
106}
107
108void memcpy8() {
109  int a[4] = {0};
110  memcpy(a+1, a+2, 8); // expected-warning{{overlapping}}
111}
112
113void memcpy9() {
114  int a[4] = {0};
115  memcpy(a+2, a+1, 4); // no-warning
116  memcpy(a+1, a+2, 4); // no-warning
117}
118
119void memcpy10() {
120  char a[4] = {0};
121  memcpy(0, a, 4); // expected-warning{{Null pointer argument in call to byte string function}}
122}
123
124void memcpy11() {
125  char a[4] = {0};
126  memcpy(a, 0, 4); // expected-warning{{Null pointer argument in call to byte string function}}
127}
128
129void memcpy12() {
130  char a[4] = {0};
131  memcpy(0, a, 0); // no-warning
132}
133
134void memcpy13() {
135  char a[4] = {0};
136  memcpy(a, 0, 0); // no-warning
137}
138
139//===----------------------------------------------------------------------===
140// mempcpy()
141//===----------------------------------------------------------------------===
142
143#define mempcpy BUILTIN(mempcpy)
144void *mempcpy(void *restrict s1, const void *restrict s2, size_t n);
145
146void mempcpy0 () {
147  char src[] = {1, 2, 3, 4};
148  char dst[5] = {0};
149
150  mempcpy(dst, src, 4); // no-warning
151
152  if (mempcpy(dst, src, 4) != &dst[4]) {
153    (void)*(char*)0; // no-warning
154  }
155
156  if (dst[0] != 0)
157    (void)*(char*)0; // expected-warning{{null}}
158}
159
160void mempcpy1 () {
161  char src[] = {1, 2, 3, 4};
162  char dst[10];
163
164  mempcpy(dst, src, 5); // expected-warning{{Byte string function accesses out-of-bound array element}}
165}
166
167void mempcpy2 () {
168  char src[] = {1, 2, 3, 4};
169  char dst[1];
170
171  mempcpy(dst, src, 4); // expected-warning{{Byte string function overflows destination buffer}}
172}
173
174void mempcpy3 () {
175  char src[] = {1, 2, 3, 4};
176  char dst[3];
177
178  mempcpy(dst+1, src+2, 2); // no-warning
179}
180
181void mempcpy4 () {
182  char src[] = {1, 2, 3, 4};
183  char dst[10];
184
185  mempcpy(dst+2, src+2, 3); // expected-warning{{Byte string function accesses out-of-bound array element}}
186}
187
188void mempcpy5() {
189  char src[] = {1, 2, 3, 4};
190  char dst[3];
191
192  mempcpy(dst+2, src+2, 2); // expected-warning{{Byte string function overflows destination buffer}}
193}
194
195void mempcpy6() {
196  int a[4] = {0};
197  mempcpy(a, a, 8); // expected-warning{{overlapping}}
198}
199
200void mempcpy7() {
201  int a[4] = {0};
202  mempcpy(a+2, a+1, 8); // expected-warning{{overlapping}}
203}
204
205void mempcpy8() {
206  int a[4] = {0};
207  mempcpy(a+1, a+2, 8); // expected-warning{{overlapping}}
208}
209
210void mempcpy9() {
211  int a[4] = {0};
212  mempcpy(a+2, a+1, 4); // no-warning
213  mempcpy(a+1, a+2, 4); // no-warning
214}
215
216void mempcpy10() {
217  char a[4] = {0};
218  mempcpy(0, a, 4); // expected-warning{{Null pointer argument in call to byte string function}}
219}
220
221void mempcpy11() {
222  char a[4] = {0};
223  mempcpy(a, 0, 4); // expected-warning{{Null pointer argument in call to byte string function}}
224}
225
226void mempcpy12() {
227  char a[4] = {0};
228  mempcpy(0, a, 0); // no-warning
229}
230
231void mempcpy13() {
232  char a[4] = {0};
233  mempcpy(a, 0, 0); // no-warning
234}
235
236//===----------------------------------------------------------------------===
237// memmove()
238//===----------------------------------------------------------------------===
239
240#ifdef VARIANT
241
242#define __memmove_chk BUILTIN(__memmove_chk)
243void *__memmove_chk(void *s1, const void *s2, size_t n, size_t destlen);
244
245#define memmove(a,b,c) __memmove_chk(a,b,c,(size_t)-1)
246
247#else /* VARIANT */
248
249#define memmove BUILTIN(memmove)
250void *memmove(void *s1, const void *s2, size_t n);
251
252#endif /* VARIANT */
253
254
255void memmove0 () {
256  char src[] = {1, 2, 3, 4};
257  char dst[4] = {0};
258
259  memmove(dst, src, 4); // no-warning
260
261  if (memmove(dst, src, 4) != dst) {
262    (void)*(char*)0; // no-warning
263  }
264
265  if (dst[0] != 0)
266    (void)*(char*)0; // expected-warning{{null}}
267}
268
269void memmove1 () {
270  char src[] = {1, 2, 3, 4};
271  char dst[10];
272
273  memmove(dst, src, 5); // expected-warning{{out-of-bound}}
274}
275
276void memmove2 () {
277  char src[] = {1, 2, 3, 4};
278  char dst[1];
279
280  memmove(dst, src, 4); // expected-warning{{overflow}}
281}
282
283//===----------------------------------------------------------------------===
284// memcmp()
285//===----------------------------------------------------------------------===
286
287#ifdef VARIANT
288
289#define bcmp BUILTIN(bcmp)
290// __builtin_bcmp is not defined with const in Builtins.def.
291int bcmp(/*const*/ void *s1, /*const*/ void *s2, size_t n);
292#define memcmp bcmp
293
294#else /* VARIANT */
295
296#define memcmp BUILTIN(memcmp)
297int memcmp(const void *s1, const void *s2, size_t n);
298
299#endif /* VARIANT */
300
301
302void memcmp0 () {
303  char a[] = {1, 2, 3, 4};
304  char b[4] = { 0 };
305
306  memcmp(a, b, 4); // no-warning
307}
308
309void memcmp1 () {
310  char a[] = {1, 2, 3, 4};
311  char b[10] = { 0 };
312
313  memcmp(a, b, 5); // expected-warning{{out-of-bound}}
314}
315
316void memcmp2 () {
317  char a[] = {1, 2, 3, 4};
318  char b[1] = { 0 };
319
320  memcmp(a, b, 4); // expected-warning{{out-of-bound}}
321}
322
323void memcmp3 () {
324  char a[] = {1, 2, 3, 4};
325
326  if (memcmp(a, a, 4))
327    (void)*(char*)0; // no-warning
328}
329
330void memcmp4 (char *input) {
331  char a[] = {1, 2, 3, 4};
332
333  if (memcmp(a, input, 4))
334    (void)*(char*)0; // expected-warning{{null}}
335}
336
337void memcmp5 (char *input) {
338  char a[] = {1, 2, 3, 4};
339
340  if (memcmp(a, 0, 0)) // no-warning
341    (void)*(char*)0;   // no-warning
342  if (memcmp(0, a, 0)) // no-warning
343    (void)*(char*)0;   // no-warning
344  if (memcmp(a, input, 0)) // no-warning
345    (void)*(char*)0;   // no-warning
346}
347
348void memcmp6 (char *a, char *b, size_t n) {
349  int result = memcmp(a, b, n);
350  if (result != 0)
351    return;
352  if (n == 0)
353    (void)*(char*)0; // expected-warning{{null}}
354}
355
356int memcmp7 (char *a, size_t x, size_t y, size_t n) {
357  // We used to crash when either of the arguments was unknown.
358  return memcmp(a, &a[x*y], n) +
359         memcmp(&a[x*y], a, n);
360}
361
362//===----------------------------------------------------------------------===
363// bcopy()
364//===----------------------------------------------------------------------===
365
366#define bcopy BUILTIN(bcopy)
367// __builtin_bcopy is not defined with const in Builtins.def.
368void bcopy(/*const*/ void *s1, void *s2, size_t n);
369
370
371void bcopy0 () {
372  char src[] = {1, 2, 3, 4};
373  char dst[4] = {0};
374
375  bcopy(src, dst, 4); // no-warning
376
377  if (dst[0] != 0)
378    (void)*(char*)0; // expected-warning{{null}}
379}
380
381void bcopy1 () {
382  char src[] = {1, 2, 3, 4};
383  char dst[10];
384
385  bcopy(src, dst, 5); // expected-warning{{out-of-bound}}
386}
387
388void bcopy2 () {
389  char src[] = {1, 2, 3, 4};
390  char dst[1];
391
392  bcopy(src, dst, 4); // expected-warning{{overflow}}
393}
394