malloc-annotations.c revision 0860cd0646ed40f87085df39563f2c5f7f77750b
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 __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
131int * af4() {
132  int *p = my_malloc(12);
133  my_free(p);
134  return p; // expected-warning{{Use of dynamically allocated}}
135}
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);
200  x[0] = 'a'; // expected-warning{{Use of dynamically allocated memory after it is freed.}}
201}
202
203void f7_realloc() {
204  char *x = (char*) malloc(4);
205  realloc(x,0);
206  x[0] = 'a'; // expected-warning{{Use of dynamically allocated memory after it is freed.}}
207}
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}
262