bstring.c revision ccbf7eebc8425429e8fd9f9124770f86a74864eb
1// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s
2// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s
3// RUN: %clang_cc1 -analyze -DCHECK -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s
4// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DCHECK -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s
5
6//===----------------------------------------------------------------------===
7// Declarations
8//===----------------------------------------------------------------------===
9
10// Some functions having a checking variant, which checks if there is overflow
11// using a flow-insensitive calculation of the buffer size. If CHECK is defined,
12// use those instead to make sure they are still checked by the analyzer.
13
14// Some functions are implemented as builtins. These should be #defined as
15// BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.
16
17// Functions that have both checking and builtin variants should be declared
18// carefully! See memcpy() for an example.
19
20#ifdef USE_BUILTINS
21# define BUILTIN(f) __builtin_ ## f
22#else /* USE_BUILTINS */
23# define BUILTIN(f) f
24#endif /* USE_BUILTINS */
25
26typedef typeof(sizeof(int)) size_t;
27
28//===----------------------------------------------------------------------===
29// memcpy()
30//===----------------------------------------------------------------------===
31
32#ifdef CHECK
33
34#define __memcpy_chk BUILTIN(__memcpy_chk)
35void *__memcpy_chk(void *restrict s1, const void *restrict s2, size_t n,
36                   size_t destlen);
37
38#define memcpy(a,b,c) __memcpy_chk(a,b,c,(size_t)-1)
39
40#else /* CHECK */
41
42#define memcpy BUILTIN(memcpy)
43void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
44
45#endif /* CHECK */
46
47
48void memcpy0 () {
49  char src[] = {1, 2, 3, 4};
50  char dst[4];
51
52  memcpy(dst, src, 4); // no-warning
53
54  if (memcpy(dst, src, 4) != dst) {
55    (void)*(char*)0; // no-warning -- should be unreachable
56  }
57}
58
59void memcpy1 () {
60  char src[] = {1, 2, 3, 4};
61  char dst[10];
62
63  memcpy(dst, src, 5); // expected-warning{{out-of-bound}}
64}
65
66void memcpy2 () {
67  char src[] = {1, 2, 3, 4};
68  char dst[1];
69
70  memcpy(dst, src, 4); // expected-warning{{out-of-bound}}
71}
72
73void memcpy3 () {
74  char src[] = {1, 2, 3, 4};
75  char dst[3];
76
77  memcpy(dst+1, src+2, 2); // no-warning
78}
79
80void memcpy4 () {
81  char src[] = {1, 2, 3, 4};
82  char dst[10];
83
84  memcpy(dst+2, src+2, 3); // expected-warning{{out-of-bound}}
85}
86
87void memcpy5() {
88  char src[] = {1, 2, 3, 4};
89  char dst[3];
90
91  memcpy(dst+2, src+2, 2); // expected-warning{{out-of-bound}}
92}
93
94void memcpy6() {
95  int a[4] = {0};
96  memcpy(a, a, 8); // expected-warning{{overlapping}}
97}
98
99void memcpy7() {
100  int a[4] = {0};
101  memcpy(a+2, a+1, 8); // expected-warning{{overlapping}}
102}
103
104void memcpy8() {
105  int a[4] = {0};
106  memcpy(a+1, a+2, 8); // expected-warning{{overlapping}}
107}
108
109void memcpy9() {
110  int a[4] = {0};
111  memcpy(a+2, a+1, 4); // no-warning
112  memcpy(a+1, a+2, 4); // no-warning
113}
114
115//===----------------------------------------------------------------------===
116// memmove()
117//===----------------------------------------------------------------------===
118
119#ifdef CHECK
120
121#define __memmove_chk BUILTIN(__memmove_chk)
122void *__memmove_chk(void *s1, const void *s2, size_t n, size_t destlen);
123
124#define memmove(a,b,c) __memmove_chk(a,b,c,(size_t)-1)
125
126#else /* CHECK */
127
128#define memmove BUILTIN(memmove)
129void *memmove(void *s1, const void *s2, size_t n);
130
131#endif /* CHECK */
132
133
134void memmove0 () {
135  char src[] = {1, 2, 3, 4};
136  char dst[4];
137
138  memmove(dst, src, 4); // no-warning
139
140  if (memmove(dst, src, 4) != dst) {
141    (void)*(char*)0; // no-warning -- should be unreachable
142  }
143}
144
145void memmove1 () {
146  char src[] = {1, 2, 3, 4};
147  char dst[10];
148
149  memmove(dst, src, 5); // expected-warning{{out-of-bound}}
150}
151
152void memmove2 () {
153  char src[] = {1, 2, 3, 4};
154  char dst[1];
155
156  memmove(dst, src, 4); // expected-warning{{out-of-bound}}
157}
158
159//===----------------------------------------------------------------------===
160// bcopy()
161//===----------------------------------------------------------------------===
162
163#define bcopy BUILTIN(bcopy)
164// __builtin_bcopy is not defined with const in Builtins.def.
165void bcopy(/*const*/ void *s1, void *s2, size_t n);
166
167
168void bcopy0 () {
169  char src[] = {1, 2, 3, 4};
170  char dst[4];
171
172  bcopy(src, dst, 4); // no-warning
173}
174
175void bcopy1 () {
176  char src[] = {1, 2, 3, 4};
177  char dst[10];
178
179  bcopy(src, dst, 5); // expected-warning{{out-of-bound}}
180}
181
182void bcopy2 () {
183  char src[] = {1, 2, 3, 4};
184  char dst[1];
185
186  bcopy(src, dst, 4); // expected-warning{{out-of-bound}}
187}
188