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