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