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