blob: 98dc2e7269b303e53370cebce255df3be77decde [file] [log] [blame]
Anna Zaks231361a2012-02-08 23:16:52 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,experimental.core.CastSize,experimental.unix.MallocWithAnnotations -analyzer-store=region -verify %s
2typedef __typeof(sizeof(int)) size_t;
3void *malloc(size_t);
4void free(void *);
5void *realloc(void *ptr, size_t size);
6void *calloc(size_t nmemb, size_t size);
7void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
8void __attribute((ownership_takes(malloc, 1))) my_free(void *);
9void __attribute((ownership_returns(malloc, 1))) *my_malloc2(size_t);
10void __attribute((ownership_holds(malloc, 1))) my_hold(void *);
11
12// Duplicate attributes are silly, but not an error.
13// Duplicate attribute has no extra effect.
14// If two are of different kinds, that is an error and reported as such.
15void __attribute((ownership_holds(malloc, 1)))
16__attribute((ownership_holds(malloc, 1)))
17__attribute((ownership_holds(malloc, 3))) my_hold2(void *, void *, void *);
18void *my_malloc3(size_t);
19void *myglobalpointer;
20struct stuff {
21 void *somefield;
22};
23struct stuff myglobalstuff;
24
25void f1() {
26 int *p = malloc(12);
27 return; // expected-warning{{Allocated memory never released. Potential memory leak.}}
28}
29
30void f2() {
31 int *p = malloc(12);
32 free(p);
33 free(p); // expected-warning{{Try to free a memory block that has been released}}
34}
35
36void f2_realloc_0() {
37 int *p = malloc(12);
38 realloc(p,0);
39 realloc(p,0); // expected-warning{{Try to free a memory block that has been released}}
40}
41
42void f2_realloc_1() {
43 int *p = malloc(12);
44 int *q = realloc(p,0); // no-warning
45}
46
47// ownership attributes tests
48void naf1() {
49 int *p = my_malloc3(12);
50 return; // no-warning
51}
52
53void n2af1() {
54 int *p = my_malloc2(12);
55 return; // expected-warning{{Allocated memory never released. Potential memory leak.}}
56}
57
58void af1() {
59 int *p = my_malloc(12);
60 return; // expected-warning{{Allocated memory never released. Potential memory leak.}}
61}
62
63void af1_b() {
64 int *p = my_malloc(12); // expected-warning{{Allocated memory never released. Potential memory leak.}}
65}
66
67void af1_c() {
68 myglobalpointer = my_malloc(12); // no-warning
69}
70
71void af1_d() {
72 struct stuff mystuff;
73 mystuff.somefield = my_malloc(12); // expected-warning{{Allocated memory never released. Potential memory leak.}}
74}
75
76// Test that we can pass out allocated memory via pointer-to-pointer.
77void af1_e(void **pp) {
78 *pp = my_malloc(42); // no-warning
79}
80
81void af1_f(struct stuff *somestuff) {
82 somestuff->somefield = my_malloc(12); // no-warning
83}
84
85// Allocating memory for a field via multiple indirections to our arguments is OK.
86void af1_g(struct stuff **pps) {
87 *pps = my_malloc(sizeof(struct stuff)); // no-warning
88 (*pps)->somefield = my_malloc(42); // no-warning
89}
90
91void af2() {
92 int *p = my_malloc(12);
93 my_free(p);
94 free(p); // expected-warning{{Try to free a memory block that has been released}}
95}
96
97void af2b() {
98 int *p = my_malloc(12);
99 free(p);
100 my_free(p); // expected-warning{{Try to free a memory block that has been released}}
101}
102
103void af2c() {
104 int *p = my_malloc(12);
105 free(p);
106 my_hold(p); // expected-warning{{Try to free a memory block that has been released}}
107}
108
109void af2d() {
110 int *p = my_malloc(12);
111 free(p);
112 my_hold2(0, 0, p); // expected-warning{{Try to free a memory block that has been released}}
113}
114
115// No leak if malloc returns null.
116void af2e() {
117 int *p = my_malloc(12);
118 if (!p)
119 return; // no-warning
120 free(p); // no-warning
121}
122
123// This case would inflict a double-free elsewhere.
124// However, this case is considered an analyzer bug since it causes false-positives.
125void af3() {
126 int *p = my_malloc(12);
127 my_hold(p);
128 free(p); // no-warning
129}
130
Anna Zaks231361a2012-02-08 23:16:52 +0000131int * af4() {
132 int *p = my_malloc(12);
133 my_free(p);
Anna Zaks0860cd02012-02-11 21:44:39 +0000134 return p; // expected-warning{{Use of dynamically allocated}}
Anna Zaks231361a2012-02-08 23:16:52 +0000135}
136
137// This case is (possibly) ok, be conservative
138int * af5() {
139 int *p = my_malloc(12);
140 my_hold(p);
141 return p; // no-warning
142}
143
144
145
146// This case tests that storing malloc'ed memory to a static variable which is
147// then returned is not leaked. In the absence of known contracts for functions
148// or inter-procedural analysis, this is a conservative answer.
149int *f3() {
150 static int *p = 0;
151 p = malloc(12);
152 return p; // no-warning
153}
154
155// This case tests that storing malloc'ed memory to a static global variable
156// which is then returned is not leaked. In the absence of known contracts for
157// functions or inter-procedural analysis, this is a conservative answer.
158static int *p_f4 = 0;
159int *f4() {
160 p_f4 = malloc(12);
161 return p_f4; // no-warning
162}
163
164int *f5() {
165 int *q = malloc(12);
166 q = realloc(q, 20);
167 return q; // no-warning
168}
169
170void f6() {
171 int *p = malloc(12);
172 if (!p)
173 return; // no-warning
174 else
175 free(p);
176}
177
178void f6_realloc() {
179 int *p = malloc(12);
180 if (!p)
181 return; // no-warning
182 else
183 realloc(p,0);
184}
185
186
187char *doit2();
188void pr6069() {
189 char *buf = doit2();
190 free(buf);
191}
192
193void pr6293() {
194 free(0);
195}
196
197void f7() {
198 char *x = (char*) malloc(4);
199 free(x);
Anna Zakse9ef5622012-02-10 01:11:00 +0000200 x[0] = 'a'; // expected-warning{{Use of dynamically allocated memory after it is freed.}}
Anna Zaks231361a2012-02-08 23:16:52 +0000201}
202
203void f7_realloc() {
204 char *x = (char*) malloc(4);
205 realloc(x,0);
Anna Zakse9ef5622012-02-10 01:11:00 +0000206 x[0] = 'a'; // expected-warning{{Use of dynamically allocated memory after it is freed.}}
Anna Zaks231361a2012-02-08 23:16:52 +0000207}
208
209void PR6123() {
210 int *x = malloc(11); // expected-warning{{Cast a region whose size is not a multiple of the destination type size.}}
211}
212
213void PR7217() {
214 int *buf = malloc(2); // expected-warning{{Cast a region whose size is not a multiple of the destination type size.}}
215 buf[1] = 'c'; // not crash
216}
217
218void mallocCastToVoid() {
219 void *p = malloc(2);
220 const void *cp = p; // not crash
221 free(p);
222}
223
224void mallocCastToFP() {
225 void *p = malloc(2);
226 void (*fp)() = p; // not crash
227 free(p);
228}
229
230// This tests that malloc() buffers are undefined by default
231char mallocGarbage () {
232 char *buf = malloc(2);
233 char result = buf[1]; // expected-warning{{undefined}}
234 free(buf);
235 return result;
236}
237
238// This tests that calloc() buffers need to be freed
239void callocNoFree () {
240 char *buf = calloc(2,2);
241 return; // expected-warning{{never released}}
242}
243
244// These test that calloc() buffers are zeroed by default
245char callocZeroesGood () {
246 char *buf = calloc(2,2);
247 char result = buf[3]; // no-warning
248 if (buf[1] == 0) {
249 free(buf);
250 }
251 return result; // no-warning
252}
253
254char callocZeroesBad () {
255 char *buf = calloc(2,2);
256 char result = buf[3]; // no-warning
257 if (buf[1] != 0) {
258 free(buf); // expected-warning{{never executed}}
259 }
260 return result; // expected-warning{{never released}}
261}