[RISCV] Simplify usage of SplatPat_simm5_plus1. NFC (#125340)
[llvm-project.git] / clang / test / Analysis / out-of-bounds-diagnostics.c
blob65bc28f58276fd2e078fceff63dd1257065839ab
1 // RUN: %clang_analyze_cc1 -Wno-array-bounds -analyzer-output=text \
2 // RUN: -analyzer-checker=core,alpha.security.ArrayBoundV2,unix.Malloc,optin.taint -verify %s
4 int TenElements[10];
6 void arrayUnderflow(void) {
7 TenElements[-3] = 5;
8 // expected-warning@-1 {{Out of bound access to memory preceding 'TenElements'}}
9 // expected-note@-2 {{Access of 'TenElements' at negative byte offset -12}}
12 int underflowWithDeref(void) {
13 int *p = TenElements;
14 --p;
15 return *p;
16 // expected-warning@-1 {{Out of bound access to memory preceding 'TenElements'}}
17 // expected-note@-2 {{Access of 'TenElements' at negative byte offset -4}}
20 int rng(void);
21 int getIndex(void) {
22 switch (rng()) {
23 case 1: return -152;
24 case 2: return -160;
25 case 3: return -168;
26 default: return -172;
30 void gh86959(void) {
31 // Previously code like this produced many almost-identical bug reports that
32 // only differed in the offset value. Verify that now we only see one report.
34 // expected-note@+1 {{Entering loop body}}
35 while (rng())
36 TenElements[getIndex()] = 10;
37 // expected-warning@-1 {{Out of bound access to memory preceding 'TenElements'}}
38 // expected-note@-2 {{Access of 'TenElements' at negative byte offset -688}}
41 int scanf(const char *restrict fmt, ...);
43 void taintedIndex(void) {
44 int index;
45 scanf("%d", &index);
46 // expected-note@-1 {{Taint originated here}}
47 // expected-note@-2 {{Taint propagated to the 2nd argument}}
48 TenElements[index] = 5;
49 // expected-warning@-1 {{Potential out of bound access to 'TenElements' with tainted index}}
50 // expected-note@-2 {{Access of 'TenElements' with a tainted index that may be negative or too large}}
53 void taintedIndexNonneg(void) {
54 int index;
55 scanf("%d", &index);
56 // expected-note@-1 {{Taint originated here}}
57 // expected-note@-2 {{Taint propagated to the 2nd argument}}
59 // expected-note@+2 {{Assuming 'index' is >= 0}}
60 // expected-note@+1 {{Taking false branch}}
61 if (index < 0)
62 return;
64 TenElements[index] = 5;
65 // expected-warning@-1 {{Potential out of bound access to 'TenElements' with tainted index}}
66 // expected-note@-2 {{Access of 'TenElements' with a tainted index that may be too large}}
69 void taintedIndexUnsigned(void) {
70 unsigned index;
71 scanf("%u", &index);
72 // expected-note@-1 {{Taint originated here}}
73 // expected-note@-2 {{Taint propagated to the 2nd argument}}
75 TenElements[index] = 5;
76 // expected-warning@-1 {{Potential out of bound access to 'TenElements' with tainted index}}
77 // expected-note@-2 {{Access of 'TenElements' with a tainted index that may be too large}}
80 int *taintedIndexAfterTheEndPtr(void) {
81 // NOTE: Technically speaking, this testcase does not trigger any UB because
82 // &TenElements[10] is the after-the-end pointer which is well-defined; but
83 // this is a bug-prone situation and far from the idiomatic use of
84 // `&TenElements[size]`, so it's better to report an error. This report can
85 // be easily silenced by writing TenElements+index instead of
86 // &TenElements[index].
87 int index;
88 scanf("%d", &index);
89 // expected-note@-1 {{Taint originated here}}
90 // expected-note@-2 {{Taint propagated to the 2nd argument}}
91 if (index < 0 || index > 10)
92 return TenElements;
93 // expected-note@-2 {{Assuming 'index' is >= 0}}
94 // expected-note@-3 {{Left side of '||' is false}}
95 // expected-note@-4 {{Assuming 'index' is <= 10}}
96 // expected-note@-5 {{Taking false branch}}
97 return &TenElements[index];
98 // expected-warning@-1 {{Potential out of bound access to 'TenElements' with tainted index}}
99 // expected-note@-2 {{Access of 'TenElements' with a tainted index that may be too large}}
102 void taintedOffset(void) {
103 int index;
104 scanf("%d", &index);
105 // expected-note@-1 {{Taint originated here}}
106 // expected-note@-2 {{Taint propagated to the 2nd argument}}
107 int *p = TenElements + index;
108 p[0] = 5;
109 // expected-warning@-1 {{Potential out of bound access to 'TenElements' with tainted offset}}
110 // expected-note@-2 {{Access of 'TenElements' with a tainted offset that may be negative or too large}}
113 void arrayOverflow(void) {
114 TenElements[12] = 5;
115 // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}
116 // expected-note@-2 {{Access of 'TenElements' at index 12, while it holds only 10 'int' elements}}
119 void flippedOverflow(void) {
120 12[TenElements] = 5;
121 // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}
122 // expected-note@-2 {{Access of 'TenElements' at index 12, while it holds only 10 'int' elements}}
125 int *afterTheEndPtr(void) {
126 // This is an unusual but standard-compliant way of writing (TenElements + 10).
127 return &TenElements[10]; // no-warning
130 int useAfterTheEndPtr(void) {
131 // ... but dereferencing the after-the-end pointer is still invalid.
132 return *afterTheEndPtr();
133 // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}
134 // expected-note@-2 {{Access of 'TenElements' at index 10, while it holds only 10 'int' elements}}
137 int *afterAfterTheEndPtr(void) {
138 // This is UB, it's invalid to form an after-after-the-end pointer.
139 return &TenElements[11];
140 // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}
141 // expected-note@-2 {{Access of 'TenElements' at index 11, while it holds only 10 'int' elements}}
144 int *potentialAfterTheEndPtr(int idx) {
145 if (idx < 10) { /* ...do something... */ }
146 // expected-note@-1 {{Assuming 'idx' is >= 10}}
147 // expected-note@-2 {{Taking false branch}}
148 return &TenElements[idx];
149 // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}
150 // expected-note@-2 {{Access of 'TenElements' at an overflowing index, while it holds only 10 'int' elements}}
151 // NOTE: On the idx >= 10 branch the normal "optimistic" behavior would've
152 // been continuing with the assumption that idx == 10 and the return value is
153 // a legitimate after-the-end pointer. The checker deviates from this by
154 // reporting an error because this situation is very suspicious and far from
155 // the idiomatic `&TenElements[size]` expressions. If the report is FP, the
156 // developer can easily silence it by writing TenElements+idx instead of
157 // &TenElements[idx].
160 int overflowOrUnderflow(int arg) {
161 // expected-note@+2 {{Assuming 'arg' is < 0}}
162 // expected-note@+1 {{Taking false branch}}
163 if (arg >= 0)
164 return 0;
166 return TenElements[arg - 1];
167 // expected-warning@-1 {{Out of bound access to memory around 'TenElements'}}
168 // expected-note@-2 {{Access of 'TenElements' at a negative or overflowing index, while it holds only 10 'int' elements}}
171 char TwoElements[2] = {11, 22};
172 char overflowOrUnderflowConcrete(int arg) {
173 // expected-note@#cond {{Assuming 'arg' is < 3}}
174 // expected-note@#cond {{Left side of '||' is false}}
175 // expected-note@#cond {{Assuming 'arg' is not equal to 0}}
176 // expected-note@#cond {{Left side of '||' is false}}
177 // expected-note@#cond {{Assuming 'arg' is not equal to 1}}
178 // expected-note@#cond {{Taking false branch}}
179 if (arg >= 3 || arg == 0 || arg == 1) // #cond
180 return 0;
182 return TwoElements[arg];
183 // expected-warning@-1 {{Out of bound access to memory around 'TwoElements'}}
184 // expected-note@-2 {{Access of 'TwoElements' at a negative or overflowing index, while it holds only 2 'char' elements}}
187 int scalar;
188 int scalarOverflow(void) {
189 return (&scalar)[1];
190 // expected-warning@-1 {{Out of bound access to memory after the end of 'scalar'}}
191 // expected-note@-2 {{Access of 'scalar' at index 1, while it holds only a single 'int' element}}
194 int oneElementArray[1];
195 int oneElementArrayOverflow(void) {
196 return oneElementArray[1];
197 // expected-warning@-1 {{Out of bound access to memory after the end of 'oneElementArray'}}
198 // expected-note@-2 {{Access of 'oneElementArray' at index 1, while it holds only a single 'int' element}}
201 struct vec {
202 int len;
203 double elems[64];
204 } v;
206 double arrayInStruct(void) {
207 return v.elems[64];
208 // expected-warning@-1 {{Out of bound access to memory after the end of 'v.elems'}}
209 // expected-note@-2 {{Access of 'v.elems' at index 64, while it holds only 64 'double' elements}}
212 double arrayInStructPtr(struct vec *pv) {
213 return pv->elems[64];
214 // expected-warning@-1 {{Out of bound access to memory after the end of the field 'elems'}}
215 // expected-note@-2 {{Access of the field 'elems' at index 64, while it holds only 64 'double' elements}}
218 struct item {
219 int a, b;
220 } itemArray[20] = {0};
222 int arrayOfStructs(void) {
223 return itemArray[35].a;
224 // expected-warning@-1 {{Out of bound access to memory after the end of 'itemArray'}}
225 // expected-note@-2 {{Access of 'itemArray' at index 35, while it holds only 20 'struct item' elements}}
228 int arrayOfStructsArrow(void) {
229 return (itemArray + 35)->b;
230 // expected-warning@-1 {{Out of bound access to memory after the end of 'itemArray'}}
231 // expected-note@-2 {{Access of 'itemArray' at index 35, while it holds only 20 'struct item' elements}}
234 short convertedArray(void) {
235 return ((short*)TenElements)[47];
236 // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}
237 // expected-note@-2 {{Access of 'TenElements' at index 47, while it holds only 20 'short' elements}}
240 struct two_bytes {
241 char lo, hi;
244 struct two_bytes convertedArray2(void) {
245 // We report this with byte offsets because the offset is not divisible by the element size.
246 struct two_bytes a = {0, 0};
247 char *p = (char*)&a;
248 return *((struct two_bytes*)(p + 7));
249 // expected-warning@-1 {{Out of bound access to memory after the end of 'a'}}
250 // expected-note@-2 {{Access of 'a' at byte offset 7, while it holds only 2 bytes}}
253 int intFromString(void) {
254 // We report this with byte offsets because the extent is not divisible by the element size.
255 return ((const int*)"this is a string of 33 characters")[20];
256 // expected-warning@-1 {{Out of bound access to memory after the end of the string literal}}
257 // expected-note@-2 {{Access of the string literal at byte offset 80, while it holds only 34 bytes}}
260 int intFromStringDivisible(void) {
261 // However, this is reported with indices/elements, because the extent
262 // (of the string that consists of 'a', 'b', 'c' and '\0') happens to be a
263 // multiple of 4 bytes (= sizeof(int)).
264 return ((const int*)"abc")[20];
265 // expected-warning@-1 {{Out of bound access to memory after the end of the string literal}}
266 // expected-note@-2 {{Access of the string literal at index 20, while it holds only a single 'int' element}}
269 typedef __typeof(sizeof(int)) size_t;
270 void *malloc(size_t size);
272 int *mallocRegion(void) {
273 int *mem = (int*)malloc(2*sizeof(int));
275 mem[3] = -2;
276 // expected-warning@-1 {{Out of bound access to memory after the end of the heap area}}
277 // expected-note@-2 {{Access of the heap area at index 3, while it holds only 2 'int' elements}}
278 return mem;
281 int *custom_calloc(size_t a, size_t b) {
282 size_t res;
284 return __builtin_mul_overflow(a, b, &res) ? 0 : malloc(res);
287 int *mallocRegionOverflow(void) {
288 int *mem = (int*)custom_calloc(10, sizeof(int));
290 mem[20] = 10;
291 // expected-warning@-1 {{Out of bound access to memory after the end of the heap area}}
292 // expected-note@-2 {{Access of the heap area at index 20, while it holds only 10 'int' elements}}
293 return mem;
296 int *mallocRegionDeref(void) {
297 int *mem = (int*)malloc(2*sizeof(int));
299 *(mem + 3) = -2;
300 // expected-warning@-1 {{Out of bound access to memory after the end of the heap area}}
301 // expected-note@-2 {{Access of the heap area at index 3, while it holds only 2 'int' elements}}
302 return mem;
305 void *alloca(size_t size);
307 int allocaRegion(void) {
308 int *mem = (int*)alloca(2*sizeof(int));
309 mem[3] = -2;
310 // expected-warning@-1 {{Out of bound access to memory after the end of the memory returned by 'alloca'}}
311 // expected-note@-2 {{Access of the memory returned by 'alloca' at index 3, while it holds only 2 'int' elements}}
312 return *mem;
315 int *symbolicExtent(int arg) {
316 // expected-note@+2 {{Assuming 'arg' is < 5}}
317 // expected-note@+1 {{Taking false branch}}
318 if (arg >= 5)
319 return 0;
320 int *mem = (int*)malloc(arg);
322 // TODO: without the following reference to 'arg', the analyzer would discard
323 // the range information about (the symbolic value of) 'arg'. This is
324 // incorrect because while the variable itself is inaccessible, it becomes
325 // the symbolic extent of 'mem', so we still want to reason about its
326 // potential values.
327 (void)arg;
329 mem[8] = -2;
330 // expected-warning@-1 {{Out of bound access to memory after the end of the heap area}}
331 // expected-note@-2 {{Access of 'int' element in the heap area at index 8}}
332 return mem;
335 int *symbolicExtentDiscardedRangeInfo(int arg) {
336 // This is a copy of the case 'symbolicExtent' without the '(void)arg' hack.
337 // TODO: if the analyzer can detect the out-of-bounds access within this
338 // testcase, then remove this and the `(void)arg` hack from `symbolicExtent`.
339 if (arg >= 5)
340 return 0;
341 int *mem = (int*)malloc(arg);
342 mem[8] = -2;
343 return mem;
346 void symbolicIndex(int arg) {
347 // expected-note@+2 {{Assuming 'arg' is >= 12}}
348 // expected-note@+1 {{Taking true branch}}
349 if (arg >= 12)
350 TenElements[arg] = -2;
351 // expected-warning@-1 {{Out of bound access to memory after the end of 'TenElements'}}
352 // expected-note@-2 {{Access of 'TenElements' at an overflowing index, while it holds only 10 'int' elements}}
355 int *nothingIsCertain(int x, int y) {
356 if (x >= 2)
357 return 0;
358 int *mem = (int*)malloc(x);
360 if (y >= 8)
361 mem[y] = -2;
362 // FIXME: this should produce
363 // {{Out of bound access to memory after the end of the heap area}}
364 // {{Access of 'int' element in the heap area at an overflowing index}}
365 // but apparently the analyzer isn't smart enough to deduce this.
367 // Keep constraints alive. (Without this, the overeager garbage collection of
368 // constraints would _also_ prevent the intended behavior in this testcase.)
369 (void)x;
371 return mem;