1 | // Given code 'struct aa { char s1[4]; char * s2;} a; memcpy(a.s1, ...);', |
2 | // this test checks that the CStringChecker only invalidates the destination buffer array a.s1 (instead of a.s1 and a.s2). |
3 | // At the moment the whole of the destination array content is invalidated. |
4 | // If a.s1 region has a symbolic offset, the whole region of 'a' is invalidated. |
5 | // Specific triple set to test structures of size 0. |
6 | // RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s |
7 | |
8 | typedef __typeof(sizeof(int)) size_t; |
9 | |
10 | char *strdup(const char *s); |
11 | void free(void *); |
12 | void *memcpy(void *dst, const void *src, size_t n); // expected-note{{passing argument to parameter 'dst' here}} |
13 | void *malloc(size_t n); |
14 | |
15 | void clang_analyzer_eval(int); |
16 | |
17 | struct aa { |
18 | char s1[4]; |
19 | char *s2; |
20 | }; |
21 | |
22 | // Test different types of structure initialisation. |
23 | int f0() { |
24 | struct aa a0 = {{1, 2, 3, 4}, 0}; |
25 | a0.s2 = strdup("hello"); |
26 | char input[] = {'a', 'b', 'c', 'd'}; |
27 | memcpy(a0.s1, input, 4); |
28 | clang_analyzer_eval(a0.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
29 | clang_analyzer_eval(a0.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
30 | clang_analyzer_eval(a0.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
31 | clang_analyzer_eval(a0.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
32 | clang_analyzer_eval(a0.s2 == 0); // expected-warning{{UNKNOWN}} |
33 | free(a0.s2); // no warning |
34 | return 0; |
35 | } |
36 | |
37 | int f1() { |
38 | struct aa a1; |
39 | a1.s2 = strdup("hello"); |
40 | char input[] = {'a', 'b', 'c', 'd'}; |
41 | memcpy(a1.s1, input, 4); |
42 | clang_analyzer_eval(a1.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
43 | clang_analyzer_eval(a1.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
44 | clang_analyzer_eval(a1.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
45 | clang_analyzer_eval(a1.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
46 | clang_analyzer_eval(a1.s2 == 0); // expected-warning{{UNKNOWN}} |
47 | free(a1.s2); // no warning |
48 | return 0; |
49 | } |
50 | |
51 | int f2() { |
52 | struct aa a2 = {{1, 2}}; |
53 | a2.s2 = strdup("hello"); |
54 | char input[] = {'a', 'b', 'c', 'd'}; |
55 | memcpy(a2.s1, input, 4); |
56 | clang_analyzer_eval(a2.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
57 | clang_analyzer_eval(a2.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
58 | clang_analyzer_eval(a2.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
59 | clang_analyzer_eval(a2.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
60 | clang_analyzer_eval(a2.s2 == 0); // expected-warning{{UNKNOWN}} |
61 | free(a2.s2); // no warning |
62 | return 0; |
63 | } |
64 | |
65 | int f3() { |
66 | struct aa a3 = {{1, 2, 3, 4}, 0}; |
67 | a3.s2 = strdup("hello"); |
68 | char input[] = {'a', 'b', 'c', 'd'}; |
69 | int * dest = (int*)a3.s1; |
70 | memcpy(dest, input, 4); |
71 | clang_analyzer_eval(a3.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
72 | clang_analyzer_eval(dest[0] == 'a'); // expected-warning{{UNKNOWN}} |
73 | clang_analyzer_eval(a3.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
74 | clang_analyzer_eval(dest[1] == 'b'); // expected-warning{{UNKNOWN}} |
75 | clang_analyzer_eval(a3.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
76 | clang_analyzer_eval(dest[2] == 'c'); // expected-warning{{UNKNOWN}} |
77 | clang_analyzer_eval(a3.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
78 | clang_analyzer_eval(dest[3] == 'd'); // expected-warning{{UNKNOWN}} |
79 | clang_analyzer_eval(a3.s2 == 0); // expected-warning{{UNKNOWN}} |
80 | free(a3.s2); // no warning |
81 | return 0; |
82 | } |
83 | |
84 | struct bb { |
85 | struct aa a; |
86 | char * s2; |
87 | }; |
88 | |
89 | int f4() { |
90 | struct bb b0 = {{1, 2, 3, 4}, 0}; |
91 | b0.s2 = strdup("hello"); |
92 | b0.a.s2 = strdup("hola"); |
93 | char input[] = {'a', 'b', 'c', 'd'}; |
94 | char * dest = (char*)(b0.a.s1); |
95 | memcpy(dest, input, 4); |
96 | clang_analyzer_eval(b0.a.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
97 | clang_analyzer_eval(dest[0] == 'a'); // expected-warning{{UNKNOWN}} |
98 | clang_analyzer_eval(b0.a.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
99 | clang_analyzer_eval(dest[1] == 'b'); // expected-warning{{UNKNOWN}} |
100 | clang_analyzer_eval(b0.a.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
101 | clang_analyzer_eval(dest[2] == 'c'); // expected-warning{{UNKNOWN}} |
102 | clang_analyzer_eval(b0.a.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
103 | clang_analyzer_eval(dest[3] == 'd'); // expected-warning{{UNKNOWN}} |
104 | clang_analyzer_eval(b0.s2 == 0); // expected-warning{{UNKNOWN}} |
105 | free(b0.a.s2); // no warning |
106 | free(b0.s2); // no warning |
107 | return 0; |
108 | } |
109 | |
110 | // Test that memory leaks are caught. |
111 | int f5() { |
112 | struct aa a0 = {{1, 2, 3, 4}, 0}; |
113 | a0.s2 = strdup("hello"); |
114 | char input[] = {'a', 'b', 'c', 'd'}; |
115 | memcpy(a0.s1, input, 4); |
116 | return 0; // expected-warning{{Potential leak of memory pointed to by 'a0.s2'}} |
117 | } |
118 | |
119 | int f6() { |
120 | struct aa a1; |
121 | a1.s2 = strdup("hello"); |
122 | char input[] = {'a', 'b', 'c', 'd'}; |
123 | memcpy(a1.s1, input, 4); |
124 | return 0; // expected-warning{{Potential leak of memory pointed to by 'a1.s2'}} |
125 | } |
126 | |
127 | int f7() { |
128 | struct aa a2 = {{1, 2}}; |
129 | a2.s2 = strdup("hello"); |
130 | char input[] = {'a', 'b', 'c', 'd'}; |
131 | memcpy(a2.s1, input, 4); |
132 | return 0; // expected-warning{{Potential leak of memory pointed to by 'a2.s2'}} |
133 | } |
134 | |
135 | int f8() { |
136 | struct aa a3 = {{1, 2, 3, 4}, 0}; |
137 | a3.s2 = strdup("hello"); |
138 | char input[] = {'a', 'b', 'c', 'd'}; |
139 | int * dest = (int*)a3.s1; |
140 | memcpy(dest, input, 4); |
141 | return 0; // expected-warning{{Potential leak of memory pointed to by 'a3.s2'}} |
142 | } |
143 | |
144 | int f9() { |
145 | struct bb b0 = {{1, 2, 3, 4}, 0}; |
146 | b0.s2 = strdup("hello"); |
147 | b0.a.s2 = strdup("hola"); |
148 | char input[] = {'a', 'b', 'c', 'd'}; |
149 | char * dest = (char*)(b0.a.s1); |
150 | memcpy(dest, input, 4); |
151 | free(b0.a.s2); // expected-warning{{Potential leak of memory pointed to by 'b0.s2'}} |
152 | return 0; |
153 | } |
154 | |
155 | int f10() { |
156 | struct bb b0 = {{1, 2, 3, 4}, 0}; |
157 | b0.s2 = strdup("hello"); |
158 | b0.a.s2 = strdup("hola"); |
159 | char input[] = {'a', 'b', 'c', 'd'}; |
160 | char * dest = (char*)(b0.a.s1); |
161 | memcpy(dest, input, 4); |
162 | free(b0.s2); // expected-warning{{Potential leak of memory pointed to by 'b0.a.s2'}} |
163 | return 0; |
164 | } |
165 | |
166 | // Test invalidating fields being addresses of array. |
167 | struct cc { |
168 | char * s1; |
169 | char * s2; |
170 | }; |
171 | |
172 | int f11() { |
173 | char x[4] = {1, 2}; |
174 | x[0] = 1; |
175 | x[1] = 2; |
176 | struct cc c0; |
177 | c0.s2 = strdup("hello"); |
178 | c0.s1 = &x[0]; |
179 | char input[] = {'a', 'b', 'c', 'd'}; |
180 | memcpy(c0.s1, input, 4); |
181 | clang_analyzer_eval(x[0] == 1); // expected-warning{{UNKNOWN}} |
182 | clang_analyzer_eval(x[1] == 2); // expected-warning{{UNKNOWN}} |
183 | clang_analyzer_eval(c0.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
184 | clang_analyzer_eval(c0.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
185 | clang_analyzer_eval(c0.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
186 | clang_analyzer_eval(c0.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
187 | free(c0.s2); // no-warning |
188 | return 0; |
189 | } |
190 | |
191 | // Test inverting field position between s1 and s2. |
192 | struct dd { |
193 | char *s2; |
194 | char s1[4]; |
195 | }; |
196 | |
197 | int f12() { |
198 | struct dd d0 = {0, {1, 2, 3, 4}}; |
199 | d0.s2 = strdup("hello"); |
200 | char input[] = {'a', 'b', 'c', 'd'}; |
201 | memcpy(d0.s1, input, 4); |
202 | clang_analyzer_eval(d0.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
203 | clang_analyzer_eval(d0.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
204 | clang_analyzer_eval(d0.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
205 | clang_analyzer_eval(d0.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
206 | clang_analyzer_eval(d0.s2 == 0); // expected-warning{{UNKNOWN}} |
207 | free(d0.s2); // no warning |
208 | return 0; |
209 | } |
210 | |
211 | // Test arrays of structs. |
212 | struct ee { |
213 | int a; |
214 | char b; |
215 | }; |
216 | |
217 | struct EE { |
218 | struct ee s1[2]; |
219 | char * s2; |
220 | }; |
221 | |
222 | int f13() { |
223 | struct EE E0 = {{{1, 2}, {3, 4}}, 0}; |
224 | E0.s2 = strdup("hello"); |
225 | char input[] = {'a', 'b', 'c', 'd'}; |
226 | memcpy(E0.s1, input, 4); |
227 | clang_analyzer_eval(E0.s1[0].a == 'a'); // expected-warning{{UNKNOWN}} |
228 | clang_analyzer_eval(E0.s1[0].b == 'b'); // expected-warning{{UNKNOWN}} |
229 | clang_analyzer_eval(E0.s1[1].a == 'c'); // expected-warning{{UNKNOWN}} |
230 | clang_analyzer_eval(E0.s1[1].b == 'd'); // expected-warning{{UNKNOWN}} |
231 | clang_analyzer_eval(E0.s2 == 0); // expected-warning{{UNKNOWN}} |
232 | free(E0.s2); // no warning |
233 | return 0; |
234 | } |
235 | |
236 | // Test global parameters. |
237 | struct aa a15 = {{1, 2, 3, 4}, 0}; |
238 | |
239 | int f15() { |
240 | a15.s2 = strdup("hello"); |
241 | char input[] = {'a', 'b', 'c', 'd'}; |
242 | memcpy(a15.s1, input, 4); |
243 | clang_analyzer_eval(a15.s1[0] == 'a'); // expected-warning{{UNKNOWN}} |
244 | clang_analyzer_eval(a15.s1[1] == 'b'); // expected-warning{{UNKNOWN}} |
245 | clang_analyzer_eval(a15.s1[2] == 'c'); // expected-warning{{UNKNOWN}} |
246 | clang_analyzer_eval(a15.s1[3] == 'd'); // expected-warning{{UNKNOWN}} |
247 | clang_analyzer_eval(a15.s2 == 0); // expected-warning{{UNKNOWN}} |
248 | free(a15.s2); // no warning |
249 | return 0; |
250 | } |
251 | |
252 | // Test array of 0 sized elements. |
253 | struct empty {}; |
254 | struct gg { |
255 | struct empty s1[4]; |
256 | char * s2; |
257 | }; |
258 | |
259 | int f16() { |
260 | struct gg g0 = {{}, 0}; |
261 | g0.s2 = strdup("hello"); |
262 | char input[] = {'a', 'b', 'c', 'd'}; |
263 | memcpy(g0.s1, input, 4); |
264 | clang_analyzer_eval(*(int*)(&g0.s1[0]) == 'a'); // expected-warning{{UNKNOWN}}\ |
265 | expected-warning{{Potential leak of memory pointed to by 'g0.s2'}} |
266 | clang_analyzer_eval(*(int*)(&g0.s1[1]) == 'b'); // expected-warning{{UNKNOWN}} |
267 | clang_analyzer_eval(*(int*)(&g0.s1[2]) == 'c'); // expected-warning{{UNKNOWN}} |
268 | clang_analyzer_eval(*(int*)(&g0.s1[3]) == 'd'); // expected-warning{{UNKNOWN}} |
269 | clang_analyzer_eval(g0.s2 == 0); // expected-warning{{UNKNOWN}} |
270 | free(g0.s2); // no warning |
271 | return 0; |
272 | } |
273 | |
274 | // Test array of 0 elements. |
275 | struct hh { |
276 | char s1[0]; |
277 | char * s2; |
278 | }; |
279 | |
280 | int f17() { |
281 | struct hh h0; |
282 | h0.s2 = strdup("hello"); |
283 | char input[] = {'a', 'b', 'c', 'd'}; |
284 | memcpy(h0.s1, input, 4); |
285 | clang_analyzer_eval(h0.s1[0] == 'a'); // expected-warning{{UNKNOWN}}\ |
286 | expected-warning{{Potential leak of memory pointed to by 'h0.s2'}} |
287 | clang_analyzer_eval(h0.s2 == 0); // expected-warning{{UNKNOWN}} |
288 | free(h0.s2); // no warning |
289 | return 0; |
290 | } |
291 | |
292 | // Test writing past the array. |
293 | struct ii { |
294 | char s1[4]; |
295 | int i; |
296 | int j; |
297 | char * s2; |
298 | }; |
299 | |
300 | int f18() { |
301 | struct ii i18 = {{1, 2, 3, 4}, 5, 6}; |
302 | i18.i = 10; |
303 | i18.j = 11; |
304 | i18.s2 = strdup("hello"); |
305 | char input[100] = {3}; |
306 | memcpy(i18.s1, input, 100); // expected-warning {{'memcpy' will always overflow; destination buffer has size 24, but size argument is 100}} |
307 | clang_analyzer_eval(i18.s1[0] == 1); // expected-warning{{UNKNOWN}}\ |
308 | expected-warning{{Potential leak of memory pointed to by 'i18.s2'}} |
309 | clang_analyzer_eval(i18.s1[1] == 2); // expected-warning{{UNKNOWN}} |
310 | clang_analyzer_eval(i18.s1[2] == 3); // expected-warning{{UNKNOWN}} |
311 | clang_analyzer_eval(i18.s1[3] == 4); // expected-warning{{UNKNOWN}} |
312 | clang_analyzer_eval(i18.i == 10); // expected-warning{{UNKNOWN}} |
313 | clang_analyzer_eval(i18.j == 11); // expected-warning{{UNKNOWN}} |
314 | return 0; |
315 | } |
316 | |
317 | int f181() { |
318 | struct ii i181 = {{1, 2, 3, 4}, 5, 6}; |
319 | i181.i = 10; |
320 | i181.j = 11; |
321 | i181.s2 = strdup("hello"); |
322 | char input[100] = {3}; |
323 | memcpy(i181.s1, input, 5); // invalidate the whole region of i181 |
324 | clang_analyzer_eval(i181.s1[0] == 1); // expected-warning{{UNKNOWN}}\ |
325 | expected-warning{{Potential leak of memory pointed to by 'i181.s2'}} |
326 | clang_analyzer_eval(i181.s1[1] == 2); // expected-warning{{UNKNOWN}} |
327 | clang_analyzer_eval(i181.s1[2] == 3); // expected-warning{{UNKNOWN}} |
328 | clang_analyzer_eval(i181.s1[3] == 4); // expected-warning{{UNKNOWN}} |
329 | clang_analyzer_eval(i181.i == 10); // expected-warning{{UNKNOWN}} |
330 | clang_analyzer_eval(i181.j == 11); // expected-warning{{UNKNOWN}} |
331 | return 0; |
332 | } |
333 | |
334 | // Test array with a symbolic offset. |
335 | struct jj { |
336 | char s1[2]; |
337 | char * s2; |
338 | }; |
339 | |
340 | struct JJ { |
341 | struct jj s1[3]; |
342 | char * s2; |
343 | }; |
344 | |
345 | int f19(int i) { |
346 | struct JJ J0 = {{{1, 2, 0}, {3, 4, 0}, {5, 6, 0}}, 0}; |
347 | J0.s2 = strdup("hello"); |
348 | J0.s1[0].s2 = strdup("hello"); |
349 | J0.s1[1].s2 = strdup("hi"); |
350 | J0.s1[2].s2 = strdup("world"); |
351 | char input[2] = {'a', 'b'}; |
352 | memcpy(J0.s1[i].s1, input, 2); |
353 | clang_analyzer_eval(J0.s1[0].s1[0] == 1); // expected-warning{{UNKNOWN}}\ |
354 | expected-warning{{Potential leak of memory pointed to by field 's2'}}\ |
355 | expected-warning{{Potential leak of memory pointed to by 'J0.s2'}} |
356 | clang_analyzer_eval(J0.s1[0].s1[1] == 2); // expected-warning{{UNKNOWN}} |
357 | clang_analyzer_eval(J0.s1[1].s1[0] == 3); // expected-warning{{UNKNOWN}} |
358 | clang_analyzer_eval(J0.s1[1].s1[1] == 4); // expected-warning{{UNKNOWN}} |
359 | clang_analyzer_eval(J0.s1[2].s1[0] == 5); // expected-warning{{UNKNOWN}} |
360 | clang_analyzer_eval(J0.s1[2].s1[1] == 6); // expected-warning{{UNKNOWN}} |
361 | clang_analyzer_eval(J0.s1[i].s1[0] == 5); // expected-warning{{UNKNOWN}} |
362 | clang_analyzer_eval(J0.s1[i].s1[1] == 6); // expected-warning{{UNKNOWN}} |
363 | // FIXME: memory leak warning for J0.s2 should be emitted here instead of after memcpy call. |
364 | return 0; // no warning |
365 | } |
366 | |
367 | // Test array with its super region having symbolic offseted regions. |
368 | int f20(int i) { |
369 | struct aa * a20 = malloc(sizeof(struct aa) * 2); |
370 | a20[0].s1[0] = 1; |
371 | a20[0].s1[1] = 2; |
372 | a20[0].s1[2] = 3; |
373 | a20[0].s1[3] = 4; |
374 | a20[0].s2 = strdup("hello"); |
375 | a20[1].s1[0] = 5; |
376 | a20[1].s1[1] = 6; |
377 | a20[1].s1[2] = 7; |
378 | a20[1].s1[3] = 8; |
379 | a20[1].s2 = strdup("world"); |
380 | a20[i].s2 = strdup("hola"); |
381 | char input[] = {'a', 'b', 'c', 'd'}; |
382 | memcpy(a20[0].s1, input, 4); |
383 | clang_analyzer_eval(a20[0].s1[0] == 1); // expected-warning{{UNKNOWN}} |
384 | clang_analyzer_eval(a20[0].s1[1] == 1); // expected-warning{{UNKNOWN}} |
385 | clang_analyzer_eval(a20[0].s1[2] == 1); // expected-warning{{UNKNOWN}} |
386 | clang_analyzer_eval(a20[0].s1[3] == 1); // expected-warning{{UNKNOWN}} |
387 | clang_analyzer_eval(a20[0].s2 == 0); // expected-warning{{UNKNOWN}} |
388 | clang_analyzer_eval(a20[1].s1[0] == 1); // expected-warning{{UNKNOWN}} |
389 | clang_analyzer_eval(a20[1].s1[1] == 1); // expected-warning{{UNKNOWN}} |
390 | clang_analyzer_eval(a20[1].s1[2] == 1); // expected-warning{{UNKNOWN}} |
391 | clang_analyzer_eval(a20[1].s1[3] == 1); // expected-warning{{UNKNOWN}} |
392 | clang_analyzer_eval(a20[1].s2 == 0); // expected-warning{{UNKNOWN}} |
393 | clang_analyzer_eval(a20[i].s1[0] == 1); // expected-warning{{UNKNOWN}} |
394 | clang_analyzer_eval(a20[i].s1[1] == 1); // expected-warning{{UNKNOWN}} |
395 | clang_analyzer_eval(a20[i].s1[2] == 1); // expected-warning{{UNKNOWN}} |
396 | clang_analyzer_eval(a20[i].s1[3] == 1); // expected-warning{{UNKNOWN}} |
397 | clang_analyzer_eval(a20[i].s2 == 0); // expected-warning{{UNKNOWN}}\ |
398 | expected-warning{{Potential leak of memory pointed to by 'a20'}} |
399 | |
400 | return 0; |
401 | } |
402 | |
403 | // Test array's region and super region both having symbolic offsets. |
404 | int f21(int i) { |
405 | struct aa * a21 = malloc(sizeof(struct aa) * 2); |
406 | a21[0].s1[0] = 1; |
407 | a21[0].s1[1] = 2; |
408 | a21[0].s1[2] = 3; |
409 | a21[0].s1[3] = 4; |
410 | a21[0].s2 = 0; |
411 | a21[1].s1[0] = 5; |
412 | a21[1].s1[1] = 6; |
413 | a21[1].s1[2] = 7; |
414 | a21[1].s1[3] = 8; |
415 | a21[1].s2 = 0; |
416 | a21[i].s2 = strdup("hello"); |
417 | a21[i].s1[0] = 1; |
418 | a21[i].s1[1] = 2; |
419 | a21[i].s1[2] = 3; |
420 | a21[i].s1[3] = 4; |
421 | char input[] = {'a', 'b', 'c', 'd'}; |
422 | memcpy(a21[i].s1, input, 4); |
423 | clang_analyzer_eval(a21[0].s1[0] == 1); // expected-warning{{UNKNOWN}} |
424 | clang_analyzer_eval(a21[0].s1[1] == 1); // expected-warning{{UNKNOWN}} |
425 | clang_analyzer_eval(a21[0].s1[2] == 1); // expected-warning{{UNKNOWN}} |
426 | clang_analyzer_eval(a21[0].s1[3] == 1); // expected-warning{{UNKNOWN}} |
427 | clang_analyzer_eval(a21[0].s2 == 0); // expected-warning{{UNKNOWN}} |
428 | clang_analyzer_eval(a21[1].s1[0] == 1); // expected-warning{{UNKNOWN}} |
429 | clang_analyzer_eval(a21[1].s1[1] == 1); // expected-warning{{UNKNOWN}} |
430 | clang_analyzer_eval(a21[1].s1[2] == 1); // expected-warning{{UNKNOWN}} |
431 | clang_analyzer_eval(a21[1].s1[3] == 1); // expected-warning{{UNKNOWN}} |
432 | clang_analyzer_eval(a21[1].s2 == 0); // expected-warning{{UNKNOWN}} |
433 | clang_analyzer_eval(a21[i].s1[0] == 1); // expected-warning{{UNKNOWN}} |
434 | clang_analyzer_eval(a21[i].s1[1] == 1); // expected-warning{{UNKNOWN}} |
435 | clang_analyzer_eval(a21[i].s1[2] == 1); // expected-warning{{UNKNOWN}} |
436 | clang_analyzer_eval(a21[i].s1[3] == 1); // expected-warning{{UNKNOWN}} |
437 | clang_analyzer_eval(a21[i].s2 == 0); // expected-warning{{UNKNOWN}}\ |
438 | expected-warning{{Potential leak of memory pointed to by 'a21'}} |
439 | |
440 | return 0; |
441 | } |
442 | |
443 | // Test regions aliasing other regions. |
444 | struct ll { |
445 | char s1[4]; |
446 | char * s2; |
447 | }; |
448 | |
449 | struct mm { |
450 | char s3[4]; |
451 | char * s4; |
452 | }; |
453 | |
454 | int f24() { |
455 | struct ll l24 = {{1, 2, 3, 4}, 0}; |
456 | struct mm * m24 = (struct mm *)&l24; |
457 | m24->s4 = strdup("hello"); |
458 | char input[] = {1, 2, 3, 4}; |
459 | memcpy(m24->s3, input, 4); |
460 | clang_analyzer_eval(m24->s3[0] == 1); // expected-warning{{UNKNOWN}} |
461 | clang_analyzer_eval(m24->s3[1] == 1); // expected-warning{{UNKNOWN}} |
462 | clang_analyzer_eval(m24->s3[2] == 1); // expected-warning{{UNKNOWN}} |
463 | clang_analyzer_eval(m24->s3[3] == 1); // expected-warning{{UNKNOWN}} |
464 | clang_analyzer_eval(l24.s1[0] == 1); // expected-warning{{UNKNOWN}} |
465 | clang_analyzer_eval(l24.s1[1] == 1); // expected-warning{{UNKNOWN}} |
466 | clang_analyzer_eval(l24.s1[2] == 1); // expected-warning{{UNKNOWN}} |
467 | clang_analyzer_eval(l24.s1[3] == 1); // expected-warning{{UNKNOWN}}\ |
468 | expected-warning{{Potential leak of memory pointed to by field 's4'}} |
469 | return 0; |
470 | } |
471 | |
472 | // Test region with potential aliasing and symbolic offsets. |
473 | // Store assumes no aliasing. |
474 | int f25(int i, int j, struct ll * l, struct mm * m) { |
475 | m->s4 = strdup("hola"); // m->s4 not tracked |
476 | m->s3[0] = 1; |
477 | m->s3[1] = 2; |
478 | m->s3[2] = 3; |
479 | m->s3[3] = 4; |
480 | m->s3[j] = 5; // invalidates m->s3 |
481 | l->s2 = strdup("hello"); // l->s2 not tracked |
482 | l->s1[0] = 6; |
483 | l->s1[1] = 7; |
484 | l->s1[2] = 8; |
485 | l->s1[3] = 9; |
486 | l->s1[i] = 10; // invalidates l->s1 |
487 | char input[] = {1, 2, 3, 4}; |
488 | memcpy(m->s3, input, 4); // does not invalidate l->s1[i] |
489 | clang_analyzer_eval(m->s3[0] == 1); // expected-warning{{UNKNOWN}} |
490 | clang_analyzer_eval(m->s3[1] == 1); // expected-warning{{UNKNOWN}} |
491 | clang_analyzer_eval(m->s3[2] == 1); // expected-warning{{UNKNOWN}} |
492 | clang_analyzer_eval(m->s3[3] == 1); // expected-warning{{UNKNOWN}} |
493 | clang_analyzer_eval(m->s3[i] == 1); // expected-warning{{UNKNOWN}} |
494 | clang_analyzer_eval(m->s3[j] == 1); // expected-warning{{UNKNOWN}} |
495 | clang_analyzer_eval(l->s1[0] == 1); // expected-warning{{UNKNOWN}} |
496 | clang_analyzer_eval(l->s1[1] == 1); // expected-warning{{UNKNOWN}} |
497 | clang_analyzer_eval(l->s1[2] == 1); // expected-warning{{UNKNOWN}} |
498 | clang_analyzer_eval(l->s1[3] == 1); // expected-warning{{UNKNOWN}} |
499 | clang_analyzer_eval(l->s1[i] == 1); // expected-warning{{FALSE}} |
500 | clang_analyzer_eval(l->s1[j] == 1); // expected-warning{{UNKNOWN}} |
501 | return 0; |
502 | } |
503 | |
504 | // Test size with symbolic size argument. |
505 | int f26(int i) { |
506 | struct aa a26 = {{1, 2, 3, 4}, 0}; |
507 | a26.s2 = strdup("hello"); |
508 | char input[] = {'a', 'b', 'c', 'd'}; |
509 | memcpy(a26.s1, input, i); // i assumed in bound |
510 | clang_analyzer_eval(a26.s1[0] == 1); // expected-warning{{UNKNOWN}} |
511 | clang_analyzer_eval(a26.s1[1] == 1); // expected-warning{{UNKNOWN}} |
512 | clang_analyzer_eval(a26.s1[2] == 1); // expected-warning{{UNKNOWN}} |
513 | clang_analyzer_eval(a26.s1[3] == 1); // expected-warning{{UNKNOWN}}\ |
514 | expected-warning{{Potential leak of memory pointed to by 'a26.s2'}} |
515 | return 0; |
516 | } |
517 | |
518 | // Test sizeof as a size argument. |
519 | int f261() { |
520 | struct aa a261 = {{1, 2, 3, 4}, 0}; |
521 | a261.s2 = strdup("hello"); |
522 | char input[] = {'a', 'b', 'c', 'd'}; |
523 | memcpy(a261.s1, input, sizeof(a261.s1)); |
524 | clang_analyzer_eval(a261.s1[0] == 1); // expected-warning{{UNKNOWN}} |
525 | clang_analyzer_eval(a261.s1[1] == 1); // expected-warning{{UNKNOWN}} |
526 | clang_analyzer_eval(a261.s1[2] == 1); // expected-warning{{UNKNOWN}} |
527 | clang_analyzer_eval(a261.s1[3] == 1); // expected-warning{{UNKNOWN}}\ |
528 | expected-warning{{Potential leak of memory pointed to by 'a261.s2'}} |
529 | return 0; |
530 | } |
531 | |
532 | // Test negative size argument. |
533 | int f262() { |
534 | struct aa a262 = {{1, 2, 3, 4}, 0}; |
535 | a262.s2 = strdup("hello"); |
536 | char input[] = {'a', 'b', 'c', 'd'}; |
537 | memcpy(a262.s1, input, -1); // expected-warning{{'memcpy' will always overflow; destination buffer has size 16, but size argument is 18446744073709551615}} |
538 | clang_analyzer_eval(a262.s1[0] == 1); // expected-warning{{UNKNOWN}}\ |
539 | expected-warning{{Potential leak of memory pointed to by 'a262.s2'}} |
540 | clang_analyzer_eval(a262.s1[1] == 1); // expected-warning{{UNKNOWN}} |
541 | clang_analyzer_eval(a262.s1[2] == 1); // expected-warning{{UNKNOWN}} |
542 | clang_analyzer_eval(a262.s1[3] == 1); // expected-warning{{UNKNOWN}} |
543 | return 0; |
544 | } |
545 | |
546 | // Test size argument being an unknown value. |
547 | struct xx { |
548 | char s1[4]; |
549 | char * s2; |
550 | }; |
551 | |
552 | int f263(int n, char * len) { |
553 | struct xx x263 = {0}; |
554 | x263.s2 = strdup("hello"); |
555 | char input[] = {'a', 'b', 'c', 'd'}; |
556 | memcpy(x263.s1, input, *(len + n)); |
557 | clang_analyzer_eval(x263.s1[0] == 0); // expected-warning{{UNKNOWN}} |
558 | clang_analyzer_eval(x263.s1[1] == 0); // expected-warning{{UNKNOWN}} |
559 | clang_analyzer_eval(x263.s1[2] == 0); // expected-warning{{UNKNOWN}} |
560 | clang_analyzer_eval(x263.s1[3] == 0); // expected-warning{{UNKNOWN}} |
561 | clang_analyzer_eval(x263.s2 == 0); // expected-warning{{UNKNOWN}} |
562 | return 0; // expected-warning{{Potential leak of memory pointed to by 'x263.s2'}} |
563 | } |
564 | |
565 | |
566 | // Test casting regions with symbolic offseted sub regions. |
567 | int f27(int i) { |
568 | struct mm m27 = {{1, 2, 3, 4}, 0}; |
569 | m27.s4 = strdup("hello"); |
570 | m27.s3[i] = 5; |
571 | char input[] = {'a', 'b', 'c', 'd'}; |
572 | memcpy(((struct ll*)(&m27))->s1, input, 4); |
573 | clang_analyzer_eval(m27.s3[0] == 1); // expected-warning{{UNKNOWN}} |
574 | clang_analyzer_eval(m27.s3[1] == 1); // expected-warning{{UNKNOWN}} |
575 | clang_analyzer_eval(m27.s3[2] == 1); // expected-warning{{UNKNOWN}} |
576 | clang_analyzer_eval(m27.s3[3] == 1); // expected-warning{{UNKNOWN}} |
577 | clang_analyzer_eval(m27.s3[i] == 1); // expected-warning{{UNKNOWN}}\ |
578 | expected-warning{{Potential leak of memory pointed to by 'm27.s4'}} |
579 | return 0; |
580 | } |
581 | |
582 | int f28(int i, int j, int k, int l) { |
583 | struct mm m28[2]; |
584 | m28[i].s4 = strdup("hello"); |
585 | m28[j].s3[k] = 1; |
586 | struct ll * l28 = (struct ll*)(&m28[1]); |
587 | l28->s1[l] = 2; |
588 | char input[] = {'a', 'b', 'c', 'd'}; // expected-warning{{Potential leak of memory pointed to by field 's4'}} |
589 | memcpy(l28->s1, input, 4); |
590 | clang_analyzer_eval(m28[0].s3[0] == 1); // expected-warning{{UNKNOWN}} |
591 | clang_analyzer_eval(m28[0].s3[1] == 1); // expected-warning{{UNKNOWN}} |
592 | clang_analyzer_eval(m28[0].s3[2] == 1); // expected-warning{{UNKNOWN}} |
593 | clang_analyzer_eval(m28[0].s3[3] == 1); // expected-warning{{UNKNOWN}} |
594 | clang_analyzer_eval(m28[1].s3[0] == 1); // expected-warning{{UNKNOWN}} |
595 | clang_analyzer_eval(m28[1].s3[1] == 1); // expected-warning{{UNKNOWN}} |
596 | clang_analyzer_eval(m28[1].s3[2] == 1); // expected-warning{{UNKNOWN}} |
597 | clang_analyzer_eval(m28[1].s3[3] == 1); // expected-warning{{UNKNOWN}} |
598 | clang_analyzer_eval(m28[i].s3[0] == 1); // expected-warning{{UNKNOWN}} |
599 | clang_analyzer_eval(m28[i].s3[1] == 1); // expected-warning{{UNKNOWN}} |
600 | clang_analyzer_eval(m28[i].s3[2] == 1); // expected-warning{{UNKNOWN}} |
601 | clang_analyzer_eval(m28[i].s3[3] == 1); // expected-warning{{UNKNOWN}} |
602 | clang_analyzer_eval(m28[j].s3[k] == 1); // expected-warning{{UNKNOWN}} |
603 | clang_analyzer_eval(l28->s1[l] == 2); // expected-warning{{UNKNOWN}} |
604 | return 0; |
605 | } |
606 | |
607 | int f29(int i, int j, int k, int l, int m) { |
608 | struct mm m29[2]; |
609 | m29[i].s4 = strdup("hello"); |
610 | m29[j].s3[k] = 1; |
611 | struct ll * l29 = (struct ll*)(&m29[l]); |
612 | l29->s1[m] = 2; |
613 | char input[] = {'a', 'b', 'c', 'd'}; |
614 | memcpy(l29->s1, input, 4); |
615 | clang_analyzer_eval(m29[0].s3[0] == 1); // expected-warning{{UNKNOWN}} |
616 | clang_analyzer_eval(m29[0].s3[1] == 1); // expected-warning{{UNKNOWN}} |
617 | clang_analyzer_eval(m29[0].s3[2] == 1); // expected-warning{{UNKNOWN}} |
618 | clang_analyzer_eval(m29[0].s3[3] == 1); // expected-warning{{UNKNOWN}} |
619 | clang_analyzer_eval(m29[1].s3[0] == 1); // expected-warning{{UNKNOWN}} |
620 | clang_analyzer_eval(m29[1].s3[1] == 1); // expected-warning{{UNKNOWN}} |
621 | clang_analyzer_eval(m29[1].s3[2] == 1); // expected-warning{{UNKNOWN}} |
622 | clang_analyzer_eval(m29[1].s3[3] == 1); // expected-warning{{UNKNOWN}} |
623 | clang_analyzer_eval(m29[i].s3[0] == 1); // expected-warning{{UNKNOWN}} |
624 | clang_analyzer_eval(m29[i].s3[1] == 1); // expected-warning{{UNKNOWN}} |
625 | clang_analyzer_eval(m29[i].s3[2] == 1); // expected-warning{{UNKNOWN}} |
626 | clang_analyzer_eval(m29[i].s3[3] == 1); // expected-warning{{UNKNOWN}} |
627 | clang_analyzer_eval(m29[j].s3[k] == 1); // expected-warning{{TRUE}} |
628 | clang_analyzer_eval(l29->s1[m] == 2); // expected-warning{{UNKNOWN}} |
629 | // FIXME: Should warn that m29[i].s4 leaks. But not on the previous line, |
630 | // because l29 and m29 alias. |
631 | return 0; |
632 | } |
633 | |
634 | // Test unions' fields. |
635 | union uu { |
636 | char x; |
637 | char s1[4]; |
638 | }; |
639 | |
640 | int f30() { |
641 | union uu u30 = { .s1 = {1, 2, 3, 4}}; |
642 | char input[] = {1, 2, 3, 4}; |
643 | memcpy(u30.s1, input, 4); |
644 | clang_analyzer_eval(u30.s1[0] == 1); // expected-warning{{UNKNOWN}} |
645 | clang_analyzer_eval(u30.s1[1] == 1); // expected-warning{{UNKNOWN}} |
646 | clang_analyzer_eval(u30.s1[2] == 1); // expected-warning{{UNKNOWN}} |
647 | clang_analyzer_eval(u30.s1[3] == 1); // expected-warning{{UNKNOWN}} |
648 | clang_analyzer_eval(u30.x == 1); // expected-warning{{UNKNOWN}} |
649 | return 0; |
650 | } |
651 | |
652 | struct kk { |
653 | union uu u; |
654 | char * s2; |
655 | }; |
656 | |
657 | int f31() { |
658 | struct kk k31; |
659 | k31.s2 = strdup("hello"); |
660 | k31.u.x = 1; |
661 | char input[] = {'a', 'b', 'c', 'd'}; |
662 | memcpy(k31.u.s1, input, 4); |
663 | clang_analyzer_eval(k31.u.s1[0] == 1); // expected-warning{{UNKNOWN}}\ |
664 | expected-warning{{Potential leak of memory pointed to by 'k31.s2'}} |
665 | clang_analyzer_eval(k31.u.s1[1] == 1); // expected-warning{{UNKNOWN}} |
666 | clang_analyzer_eval(k31.u.s1[2] == 1); // expected-warning{{UNKNOWN}} |
667 | clang_analyzer_eval(k31.u.s1[3] == 1); // expected-warning{{UNKNOWN}} |
668 | clang_analyzer_eval(k31.u.x == 1); // expected-warning{{UNKNOWN}} |
669 | // FIXME: memory leak warning for k31.s2 should be emitted here. |
670 | return 0; |
671 | } |
672 | |
673 | union vv { |
674 | int x; |
675 | char * s2; |
676 | }; |
677 | |
678 | int f32() { |
679 | union vv v32; |
680 | v32.s2 = strdup("hello"); |
681 | char input[] = {'a', 'b', 'c', 'd'}; |
682 | memcpy(v32.s2, input, 4); |
683 | clang_analyzer_eval(v32.s2[0] == 1); // expected-warning{{UNKNOWN}} |
684 | clang_analyzer_eval(v32.s2[1] == 1); // expected-warning{{UNKNOWN}} |
685 | clang_analyzer_eval(v32.s2[2] == 1); // expected-warning{{UNKNOWN}} |
686 | clang_analyzer_eval(v32.s2[3] == 1); // expected-warning{{UNKNOWN}}\ |
687 | expected-warning{{Potential leak of memory pointed to by 'v32.s2'}} |
688 | return 0; |
689 | } |
690 | |
691 | struct nn { |
692 | int s1; |
693 | int i; |
694 | int j; |
695 | int k; |
696 | char * s2; |
697 | }; |
698 | |
699 | // Test bad types to dest buffer. |
700 | int f33() { |
701 | struct nn n33 = {1, 2, 3, 4, 0}; |
702 | n33.s2 = strdup("hello"); |
703 | char input[] = {'a', 'b', 'c', 'd'}; |
704 | memcpy(n33.s1, input, 4); // expected-warning{{incompatible integer to pointer conversion passing 'int' to parameter of type 'void *'}} |
705 | clang_analyzer_eval(n33.i == 2); // expected-warning{{TRUE}} |
706 | clang_analyzer_eval(n33.j == 3); // expected-warning{{TRUE}} |
707 | clang_analyzer_eval(n33.k == 4); // expected-warning{{TRUE}} |
708 | clang_analyzer_eval(((char*)(n33.s1))[0] == 1); // expected-warning{{UNKNOWN}}\ |
709 | expected-warning{{cast to 'char *' from smaller integer type 'int'}} |
710 | clang_analyzer_eval(((char*)(n33.s1))[1] == 1); // expected-warning{{UNKNOWN}}\ |
711 | expected-warning{{cast to 'char *' from smaller integer type 'int'}} |
712 | clang_analyzer_eval(((char*)(n33.s1))[2] == 1); // expected-warning{{UNKNOWN}}\ |
713 | expected-warning{{cast to 'char *' from smaller integer type 'int'}} |
714 | clang_analyzer_eval(((char*)(n33.s1))[3] == 1); // expected-warning{{UNKNOWN}}\ |
715 | expected-warning{{cast to 'char *' from smaller integer type 'int'}} |
716 | clang_analyzer_eval(n33.s2 == 0); //expected-warning{{UNKNOWN}} |
717 | return 0; // expected-warning{{Potential leak of memory pointed to by 'n33.s2'}} |
718 | } |
719 | |
720 | // Test destination buffer being an unknown value. |
721 | struct ww { |
722 | int s1[4]; |
723 | char s2; |
724 | }; |
725 | |
726 | int f34(struct ww * w34, int n) { |
727 | w34->s2 = 3; |
728 | char input[] = {'a', 'b', 'c', 'd'}; |
729 | memcpy(w34->s1 + n, input , 4); |
730 | clang_analyzer_eval(w34->s1[0] == 0); // expected-warning{{UNKNOWN}} |
731 | clang_analyzer_eval(w34->s1[1] == 0); // expected-warning{{UNKNOWN}} |
732 | clang_analyzer_eval(w34->s1[2] == 0); // expected-warning{{UNKNOWN}} |
733 | clang_analyzer_eval(w34->s1[3] == 0); // expected-warning{{UNKNOWN}} |
734 | clang_analyzer_eval(w34->s1[n] == 0); // expected-warning{{UNKNOWN}} |
735 | clang_analyzer_eval(w34->s2 == 3); // expected-warning{{TRUE}} |
736 | return 0; |
737 | } |
738 | |
739 | // Test dest buffer as an element region with a symbolic index and size parameter as a symbolic value. |
740 | struct yy { |
741 | char s1[4]; |
742 | char * s2; |
743 | }; |
744 | |
745 | int f35(int i, int n) { |
746 | struct yy y35 = {{1, 2, 3, 4}, 0}; |
747 | y35.s2 = strdup("hello"); |
748 | char input[] = {'a', 'b', 'c', 'd'}; |
749 | memcpy(&(y35.s1[i]), input, n); |
750 | clang_analyzer_eval(y35.s1[0] == 0); // expected-warning{{UNKNOWN}} |
751 | clang_analyzer_eval(y35.s1[1] == 0); // expected-warning{{UNKNOWN}} |
752 | clang_analyzer_eval(y35.s1[2] == 0); // expected-warning{{UNKNOWN}} |
753 | clang_analyzer_eval(y35.s1[3] == 0); // expected-warning{{UNKNOWN}} |
754 | clang_analyzer_eval(y35.s1[i] == 0); // expected-warning{{UNKNOWN}} |
755 | clang_analyzer_eval(y35.s2 == 0); // expected-warning{{UNKNOWN}} |
756 | return 0; // expected-warning{{Potential leak of memory pointed to by 'y35.s2'}} |
757 | } |
758 | |
759 | // Test regions with negative offsets. |
760 | struct zz { |
761 | char s1[4]; |
762 | int s2; |
763 | }; |
764 | |
765 | int f36(struct zz * z36) { |
766 | |
767 | char input[] = {'a', 'b', 'c', 'd'}; |
768 | z36->s1[0] = 0; |
769 | z36->s1[1] = 1; |
770 | z36->s1[2] = 2; |
771 | z36->s1[3] = 3; |
772 | z36->s2 = 10; |
773 | |
774 | z36 = z36 - 1; // Decrement by 8 bytes (struct zz is 8 bytes). |
775 | |
776 | z36->s1[0] = 4; |
777 | z36->s1[1] = 5; |
778 | z36->s1[2] = 6; |
779 | z36->s1[3] = 7; |
780 | z36->s2 = 11; |
781 | |
782 | memcpy(z36->s1, input, 4); |
783 | |
784 | clang_analyzer_eval(z36->s1[0] == 1); // expected-warning{{UNKNOWN}} |
785 | clang_analyzer_eval(z36->s1[1] == 1); // expected-warning{{UNKNOWN}} |
786 | clang_analyzer_eval(z36->s1[2] == 1); // expected-warning{{UNKNOWN}} |
787 | clang_analyzer_eval(z36->s1[3] == 1); // expected-warning{{UNKNOWN}} |
788 | clang_analyzer_eval(z36->s2 == 11); // expected-warning{{TRUE}} |
789 | |
790 | z36 = z36 + 1; // Increment back. |
791 | |
792 | clang_analyzer_eval(z36->s1[0] == 0); // expected-warning{{TRUE}} |
793 | clang_analyzer_eval(z36->s1[1] == 1); // expected-warning{{TRUE}} |
794 | clang_analyzer_eval(z36->s1[2] == 2); // expected-warning{{TRUE}} |
795 | clang_analyzer_eval(z36->s1[3] == 3); // expected-warning{{TRUE}} |
796 | clang_analyzer_eval(z36->s2 == 10); // expected-warning{{TRUE}} |
797 | |
798 | return 0; |
799 | } |
800 | |
801 | int f37(struct zz * z37) { |
802 | |
803 | char input[] = {'a', 'b', 'c', 'd'}; |
804 | z37->s1[0] = 0; |
805 | z37->s1[1] = 1; |
806 | z37->s1[2] = 2; |
807 | z37->s1[3] = 3; |
808 | z37->s2 = 10; |
809 | |
810 | z37 = (struct zz *)((char*)(z37) - 4); // Decrement by 4 bytes (struct zz is 8 bytes). |
811 | |
812 | z37->s1[0] = 4; |
813 | z37->s1[1] = 5; |
814 | z37->s1[2] = 6; |
815 | z37->s1[3] = 7; |
816 | z37->s2 = 11; |
817 | |
818 | memcpy(z37->s1, input, 4); |
819 | |
820 | clang_analyzer_eval(z37->s1[0] == 1); // expected-warning{{UNKNOWN}} |
821 | clang_analyzer_eval(z37->s1[1] == 1); // expected-warning{{UNKNOWN}} |
822 | clang_analyzer_eval(z37->s1[2] == 1); // expected-warning{{UNKNOWN}} |
823 | clang_analyzer_eval(z37->s1[3] == 1); // expected-warning{{UNKNOWN}} |
824 | clang_analyzer_eval(z37->s2 == 11); // expected-warning{{TRUE}} |
825 | |
826 | z37 = (struct zz *)((char*)(z37) + 4); // Increment back. |
827 | |
828 | clang_analyzer_eval(z37->s1[0] == 11); // expected-warning{{TRUE}} |
829 | clang_analyzer_eval(z37->s1[1] == 1); // expected-warning{{UNKNOWN}} |
830 | clang_analyzer_eval(z37->s1[2] == 1); // expected-warning{{UNKNOWN}} |
831 | clang_analyzer_eval(z37->s1[3] == 1); // expected-warning{{UNKNOWN}} |
832 | clang_analyzer_eval(z37->s2 == 10); // expected-warning{{TRUE}} |
833 | |
834 | return 0; |
835 | } |
836 | |
837 | int f38(struct zz * z38) { |
838 | |
839 | char input[] = {'a', 'b', 'c', 'd'}; |
840 | z38->s1[0] = 0; |
841 | z38->s1[1] = 1; |
842 | z38->s1[2] = 2; |
843 | z38->s1[3] = 3; |
844 | z38->s2 = 10; |
845 | |
846 | z38 = (struct zz *)((char*)(z38) - 2); // Decrement by 2 bytes (struct zz is 8 bytes). |
847 | |
848 | z38->s1[0] = 4; |
849 | z38->s1[1] = 5; |
850 | z38->s1[2] = 6; |
851 | z38->s1[3] = 7; |
852 | z38->s2 = 11; |
853 | |
854 | memcpy(z38->s1, input, 4); |
855 | |
856 | clang_analyzer_eval(z38->s1[0] == 1); // expected-warning{{UNKNOWN}} |
857 | clang_analyzer_eval(z38->s1[1] == 1); // expected-warning{{UNKNOWN}} |
858 | clang_analyzer_eval(z38->s1[2] == 1); // expected-warning{{UNKNOWN}} |
859 | clang_analyzer_eval(z38->s1[3] == 1); // expected-warning{{UNKNOWN}} |
860 | clang_analyzer_eval(z38->s2 == 11); // expected-warning{{TRUE}} |
861 | |
862 | z38 = (struct zz *)((char*)(z38) + 2); // Increment back. |
863 | |
864 | clang_analyzer_eval(z38->s1[0] == 1); // expected-warning{{UNKNOWN}} |
865 | clang_analyzer_eval(z38->s1[1] == 1); // expected-warning{{UNKNOWN}} |
866 | clang_analyzer_eval(z38->s1[2] == 11); // expected-warning{{TRUE}} |
867 | clang_analyzer_eval(z38->s1[3] == 1); // expected-warning{{UNKNOWN}} |
868 | clang_analyzer_eval(z38->s2 == 10); // expected-warning{{UNKNOWN}} |
869 | |
870 | return 0; |
871 | } |
872 | |
873 | // Test negative offsets with a different structure layout. |
874 | struct z0 { |
875 | int s2; |
876 | char s1[4]; |
877 | }; |
878 | |
879 | int f39(struct z0 * d39) { |
880 | |
881 | char input[] = {'a', 'b', 'c', 'd'}; |
882 | d39->s1[0] = 0; |
883 | d39->s1[1] = 1; |
884 | d39->s1[2] = 2; |
885 | d39->s1[3] = 3; |
886 | d39->s2 = 10; |
887 | |
888 | d39 = (struct z0 *)((char*)(d39) - 2); // Decrement by 2 bytes (struct z0 is 8 bytes). |
889 | |
890 | d39->s1[0] = 4; |
891 | d39->s1[1] = 5; |
892 | d39->s1[2] = 6; |
893 | d39->s1[3] = 7; |
894 | d39->s2 = 11; |
895 | |
896 | memcpy(d39->s1, input, 4); |
897 | |
898 | clang_analyzer_eval(d39->s1[0] == 1); // expected-warning{{UNKNOWN}} |
899 | clang_analyzer_eval(d39->s1[1] == 1); // expected-warning{{UNKNOWN}} |
900 | clang_analyzer_eval(d39->s1[2] == 1); // expected-warning{{UNKNOWN}} |
901 | clang_analyzer_eval(d39->s1[3] == 1); // expected-warning{{UNKNOWN}} |
902 | clang_analyzer_eval(d39->s2 == 11); // expected-warning{{TRUE}} |
903 | |
904 | d39 = (struct z0 *)((char*)(d39) + 2); // Increment back. |
905 | |
906 | clang_analyzer_eval(d39->s1[0] == 1); // expected-warning{{UNKNOWN}} |
907 | clang_analyzer_eval(d39->s1[1] == 1); // expected-warning{{UNKNOWN}} |
908 | clang_analyzer_eval(d39->s1[2] == 2); // expected-warning{{TRUE}} |
909 | clang_analyzer_eval(d39->s1[3] == 3); // expected-warning{{TRUE}} |
910 | // FIXME: d39->s2 should evaluate to at least UNKNOWN or FALSE, |
911 | // 'collectSubRegionBindings(...)' in RegionStore.cpp will need to |
912 | // handle a regions' upper boundary overflowing. |
913 | clang_analyzer_eval(d39->s2 == 10); // expected-warning{{TRUE}} |
914 | |
915 | return 0; |
916 | } |
917 | |
918 | |