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 | |
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 | #ifndef VARIANT |
77 | // expected-warning@-2{{memcpy' will always overflow; destination buffer has size 1, but size argument is 4}} |
78 | #endif |
79 | } |
80 | |
81 | void memcpy3 () { |
82 | char src[] = {1, 2, 3, 4}; |
83 | char dst[3]; |
84 | |
85 | memcpy(dst+1, src+2, 2); // no-warning |
86 | } |
87 | |
88 | void 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 | |
95 | void 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 | |
105 | void memcpy6() { |
106 | int a[4] = {0}; |
107 | memcpy(a, a, 8); // expected-warning{{overlapping}} |
108 | } |
109 | |
110 | void memcpy7() { |
111 | int a[4] = {0}; |
112 | memcpy(a+2, a+1, 8); // expected-warning{{overlapping}} |
113 | } |
114 | |
115 | void memcpy8() { |
116 | int a[4] = {0}; |
117 | memcpy(a+1, a+2, 8); // expected-warning{{overlapping}} |
118 | } |
119 | |
120 | void 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 | |
126 | void memcpy10() { |
127 | char a[4] = {0}; |
128 | memcpy(0, a, 4); // expected-warning{{Null pointer argument in call to memory copy function}} |
129 | } |
130 | |
131 | void memcpy11() { |
132 | char a[4] = {0}; |
133 | memcpy(a, 0, 4); // expected-warning{{Null pointer argument in call to memory copy function}} |
134 | } |
135 | |
136 | void memcpy12() { |
137 | char a[4] = {0}; |
138 | memcpy(0, a, 0); // no-warning |
139 | } |
140 | |
141 | void memcpy13() { |
142 | char a[4] = {0}; |
143 | memcpy(a, 0, 0); // no-warning |
144 | } |
145 | |
146 | void 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 | |
151 | void 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) |
164 | void *__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) |
172 | void *mempcpy(void *restrict s1, const void *restrict s2, size_t n); |
173 | |
174 | #endif /* VARIANT */ |
175 | |
176 | |
177 | void 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 | |
190 | void 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 | |
197 | void 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 | |
204 | void mempcpy3 () { |
205 | char src[] = {1, 2, 3, 4}; |
206 | char dst[3]; |
207 | |
208 | mempcpy(dst+1, src+2, 2); // no-warning |
209 | } |
210 | |
211 | void 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 | |
218 | void 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 | |
225 | void mempcpy6() { |
226 | int a[4] = {0}; |
227 | mempcpy(a, a, 8); // expected-warning{{overlapping}} |
228 | } |
229 | |
230 | void mempcpy7() { |
231 | int a[4] = {0}; |
232 | mempcpy(a+2, a+1, 8); // expected-warning{{overlapping}} |
233 | } |
234 | |
235 | void mempcpy8() { |
236 | int a[4] = {0}; |
237 | mempcpy(a+1, a+2, 8); // expected-warning{{overlapping}} |
238 | } |
239 | |
240 | void 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 | |
246 | void mempcpy10() { |
247 | char a[4] = {0}; |
248 | mempcpy(0, a, 4); // expected-warning{{Null pointer argument in call to memory copy function}} |
249 | } |
250 | |
251 | void mempcpy11() { |
252 | char a[4] = {0}; |
253 | mempcpy(a, 0, 4); // expected-warning{{Null pointer argument in call to memory copy function}} |
254 | } |
255 | |
256 | void mempcpy12() { |
257 | char a[4] = {0}; |
258 | mempcpy(0, a, 0); // no-warning |
259 | } |
260 | |
261 | void mempcpy13() { |
262 | char a[4] = {0}; |
263 | mempcpy(a, 0, 0); // no-warning |
264 | } |
265 | |
266 | void 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 | |
276 | struct st { |
277 | int i; |
278 | int j; |
279 | }; |
280 | |
281 | void 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 | |
293 | void 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 | |
305 | void 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 | |
311 | void 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) |
324 | void *__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) |
331 | void *memmove(void *s1, const void *s2, size_t n); |
332 | |
333 | #endif /* VARIANT */ |
334 | |
335 | |
336 | void 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 | |
349 | void 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 | |
356 | void 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) |
373 | int bcmp(const void *s1, const void *s2, size_t n); |
374 | #define memcmp bcmp |
375 | // |
376 | #else /* VARIANT */ |
377 | |
378 | #define memcmp BUILTIN(memcmp) |
379 | int memcmp(const void *s1, const void *s2, size_t n); |
380 | |
381 | #endif /* VARIANT */ |
382 | |
383 | |
384 | void memcmp0 () { |
385 | char a[] = {1, 2, 3, 4}; |
386 | char b[4] = { 0 }; |
387 | |
388 | memcmp(a, b, 4); // no-warning |
389 | } |
390 | |
391 | void 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 | |
398 | void 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 | |
405 | void memcmp3 () { |
406 | char a[] = {1, 2, 3, 4}; |
407 | |
408 | clang_analyzer_eval(memcmp(a, a, 4) == 0); // expected-warning{{TRUE}} |
409 | } |
410 | |
411 | void 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 | |
417 | void 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 | |
425 | void 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 | |
436 | int 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. |
448 | void bcopy(/*const*/ void *s1, void *s2, size_t n); |
449 | |
450 | |
451 | void 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 | |
462 | void 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 | |
469 | void bcopy2 () { |
470 | char src[] = {1, 2, 3, 4}; |
471 | char dst[1]; |
472 | |
473 | bcopy(src, dst, 4); // expected-warning{{overflow}} |
474 | } |
475 | |
476 | void *malloc(size_t); |
477 | void free(void *); |
478 | char 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 | |
486 | struct S { |
487 | char f; |
488 | }; |
489 | |
490 | void 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 | |