Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,experimental.core.CastSize,experimental.unix.MallocWithAnnotations -analyzer-store=region -verify %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{{Memory is never released; potential leak}}
     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{{Memory is never released; potential leak}}
     58 }
     59 
     60 void af1() {
     61   int *p = my_malloc(12);
     62   return; // expected-warning{{Memory is never released; potential leak}}
     63 }
     64 
     65 void af1_b() {
     66   int *p = my_malloc(12); // expected-warning{{Memory is never released; potential leak}}
     67 }
     68 
     69 void 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.
     74 void 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.
     80 void af1_e(void **pp) {
     81   *pp = my_malloc(42); // no-warning
     82 }
     83 
     84 void 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.
     89 void af1_g(struct stuff **pps) {
     90   *pps = my_malloc(sizeof(struct stuff)); // no-warning
     91   (*pps)->somefield = my_malloc(42); // no-warning
     92 }
     93 
     94 void af2() {
     95   int *p = my_malloc(12);
     96   my_free(p);
     97   free(p); // expected-warning{{Attempt to free released memory}}
     98 }
     99 
    100 void af2b() {
    101   int *p = my_malloc(12);
    102   free(p);
    103   my_free(p); // expected-warning{{Attempt to free released memory}}
    104 }
    105 
    106 void af2c() {
    107   int *p = my_malloc(12);
    108   free(p);
    109   my_hold(p); // expected-warning{{Attempt to free released memory}}
    110 }
    111 
    112 void 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.
    119 void 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.
    128 void af3() {
    129   int *p = my_malloc(12);
    130   my_hold(p);
    131   free(p); // no-warning
    132 }
    133 
    134 int * 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
    141 int * 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.
    152 int *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.
    161 static int *p_f4 = 0;
    162 int *f4() {
    163   p_f4 = malloc(12);
    164   return p_f4; // no-warning
    165 }
    166 
    167 int *f5() {
    168   int *q = malloc(12);
    169   q = realloc(q, 20);
    170   return q; // no-warning
    171 }
    172 
    173 void f6() {
    174   int *p = malloc(12);
    175   if (!p)
    176     return; // no-warning
    177   else
    178     free(p);
    179 }
    180 
    181 void f6_realloc() {
    182   int *p = malloc(12);
    183   if (!p)
    184     return; // no-warning
    185   else
    186     realloc(p,0);
    187 }
    188 
    189 
    190 char *doit2();
    191 void pr6069() {
    192   char *buf = doit2();
    193   free(buf);
    194 }
    195 
    196 void pr6293() {
    197   free(0);
    198 }
    199 
    200 void 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 
    206 void 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 
    212 void PR6123() {
    213   int *x = malloc(11); // expected-warning{{Cast a region whose size is not a multiple of the destination type size.}}
    214 }
    215 
    216 void 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 
    221 void mallocCastToVoid() {
    222   void *p = malloc(2);
    223   const void *cp = p; // not crash
    224   free(p);
    225 }
    226 
    227 void 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
    234 char 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
    242 void 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
    248 char 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 
    257 char 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 
    266 void testMultipleFreeAnnotations() {
    267   int *p = malloc(12);
    268   int *q = malloc(12);
    269   my_freeBoth(p, q);
    270 }
    271 
    272