Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s
      2 // RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s
      3 #include "Inputs/system-header-simulator-cxx.h"
      4 
      5 typedef __typeof__(sizeof(int)) size_t;
      6 extern "C" void *malloc(size_t);
      7 extern "C" void free (void* ptr);
      8 int *global;
      9 
     10 //------------------
     11 // check for leaks
     12 //------------------
     13 
     14 //----- Standard non-placement operators
     15 void testGlobalOpNew() {
     16   void *p = operator new(0);
     17 }
     18 #ifdef LEAKS
     19 // expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
     20 #endif
     21 
     22 void testGlobalOpNewArray() {
     23   void *p = operator new[](0);
     24 }
     25 #ifdef LEAKS
     26 // expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
     27 #endif
     28 
     29 void testGlobalNewExpr() {
     30   int *p = new int;
     31 }
     32 #ifdef LEAKS
     33 // expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
     34 #endif
     35 
     36 void testGlobalNewExprArray() {
     37   int *p = new int[0];
     38 }
     39 #ifdef LEAKS
     40 // expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
     41 #endif
     42 
     43 //----- Standard nothrow placement operators
     44 void testGlobalNoThrowPlacementOpNewBeforeOverload() {
     45   void *p = operator new(0, std::nothrow);
     46 }
     47 #ifdef LEAKS
     48 // expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
     49 #endif
     50 
     51 void testGlobalNoThrowPlacementExprNewBeforeOverload() {
     52   int *p = new(std::nothrow) int;
     53 }
     54 #ifdef LEAKS
     55 // expected-warning@-2{{Potential leak of memory pointed to by 'p'}}
     56 #endif
     57 
     58 //----- Standard pointer placement operators
     59 void testGlobalPointerPlacementNew() {
     60   int i;
     61 
     62   void *p1 = operator new(0, &i); // no warn
     63 
     64   void *p2 = operator new[](0, &i); // no warn
     65 
     66   int *p3 = new(&i) int; // no warn
     67 
     68   int *p4 = new(&i) int[0]; // no warn
     69 }
     70 
     71 //----- Other cases
     72 void testNewMemoryIsInHeap() {
     73   int *p = new int;
     74   if (global != p) // condition is always true as 'p' wraps a heap region that
     75                    // is different from a region wrapped by 'global'
     76     global = p; // pointer escapes
     77 }
     78 
     79 struct PtrWrapper {
     80   int *x;
     81 
     82   PtrWrapper(int *input) : x(input) {}
     83 };
     84 
     85 void testNewInvalidationPlacement(PtrWrapper *w) {
     86   // Ensure that we don't consider this a leak.
     87   new (w) PtrWrapper(new int); // no warn
     88 }
     89 
     90 //-----------------------------------------
     91 // check for usage of zero-allocated memory
     92 //-----------------------------------------
     93 
     94 void testUseZeroAlloc1() {
     95   int *p = (int *)operator new(0);
     96   *p = 1; // expected-warning {{Use of zero-allocated memory}}
     97   delete p;
     98 }
     99 
    100 int testUseZeroAlloc2() {
    101   int *p = (int *)operator new[](0);
    102   return p[0]; // expected-warning {{Use of zero-allocated memory}}
    103   delete[] p;
    104 }
    105 
    106 void f(int);
    107 
    108 void testUseZeroAlloc3() {
    109   int *p = new int[0];
    110   f(*p); // expected-warning {{Use of zero-allocated memory}}
    111   delete[] p;
    112 }
    113 
    114 //---------------
    115 // other checks
    116 //---------------
    117 
    118 class SomeClass {
    119 public:
    120   void f(int *p);
    121 };
    122 
    123 void f(int *p1, int *p2 = 0, int *p3 = 0);
    124 void g(SomeClass &c, ...);
    125 
    126 void testUseFirstArgAfterDelete() {
    127   int *p = new int;
    128   delete p;
    129   f(p); // expected-warning{{Use of memory after it is freed}}
    130 }
    131 
    132 void testUseMiddleArgAfterDelete(int *p) {
    133   delete p;
    134   f(0, p); // expected-warning{{Use of memory after it is freed}}
    135 }
    136 
    137 void testUseLastArgAfterDelete(int *p) {
    138   delete p;
    139   f(0, 0, p); // expected-warning{{Use of memory after it is freed}}
    140 }
    141 
    142 void testUseSeveralArgsAfterDelete(int *p) {
    143   delete p;
    144   f(p, p, p); // expected-warning{{Use of memory after it is freed}}
    145 }
    146 
    147 void testUseRefArgAfterDelete(SomeClass &c) {
    148   delete &c;
    149   g(c); // expected-warning{{Use of memory after it is freed}}
    150 }
    151 
    152 void testVariadicArgAfterDelete() {
    153   SomeClass c;
    154   int *p = new int;
    155   delete p;
    156   g(c, 0, p); // expected-warning{{Use of memory after it is freed}}
    157 }
    158 
    159 void testUseMethodArgAfterDelete(int *p) {
    160   SomeClass *c = new SomeClass;
    161   delete p;
    162   c->f(p); // expected-warning{{Use of memory after it is freed}}
    163 }
    164 
    165 void testUseThisAfterDelete() {
    166   SomeClass *c = new SomeClass;
    167   delete c;
    168   c->f(0); // expected-warning{{Use of memory after it is freed}}
    169 }
    170 
    171 void testDoubleDelete() {
    172   int *p = new int;
    173   delete p;
    174   delete p; // expected-warning{{Attempt to free released memory}}
    175 }
    176 
    177 void testExprDeleteArg() {
    178   int i;
    179   delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
    180 }
    181 
    182 void testExprDeleteArrArg() {
    183   int i;
    184   delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}}
    185 }
    186 
    187 void testAllocDeallocNames() {
    188   int *p = new(std::nothrow) int[1];
    189   delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}}
    190 }
    191 
    192 //--------------------------------
    193 // Test escape of newed const pointer. Note, a const pointer can be deleted.
    194 //--------------------------------
    195 struct StWithConstPtr {
    196   const int *memp;
    197 };
    198 void escape(const int &x);
    199 void escapeStruct(const StWithConstPtr &x);
    200 void escapePtr(const StWithConstPtr *x);
    201 void escapeVoidPtr(const void *x);
    202 
    203 void testConstEscape() {
    204   int *p = new int(1);
    205   escape(*p);
    206 } // no-warning
    207 
    208 void testConstEscapeStruct() {
    209   StWithConstPtr *St = new StWithConstPtr();
    210   escapeStruct(*St);
    211 } // no-warning
    212 
    213 void testConstEscapeStructPtr() {
    214   StWithConstPtr *St = new StWithConstPtr();
    215   escapePtr(St);
    216 } // no-warning
    217 
    218 void testConstEscapeMember() {
    219   StWithConstPtr St;
    220   St.memp = new int(2);
    221   escapeVoidPtr(St.memp);
    222 } // no-warning
    223 
    224 void testConstEscapePlacementNew() {
    225   int *x = (int *)malloc(sizeof(int));
    226   void *y = new (x) int;
    227   escapeVoidPtr(y);
    228 } // no-warning
    229 
    230 //============== Test Uninitialized delete delete[]========================
    231 void testUninitDelete() {
    232   int *x;
    233   int * y = new int;
    234   delete y;
    235   delete x; // expected-warning{{Argument to 'delete' is uninitialized}}
    236 }
    237 
    238 void testUninitDeleteArray() {
    239   int *x;
    240   int * y = new int[5];
    241   delete[] y;
    242   delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}}
    243 }
    244 
    245 void testUninitFree() {
    246   int *x;
    247   free(x); // expected-warning{{Function call argument is an uninitialized value}}
    248 }
    249 
    250 void testUninitDeleteSink() {
    251   int *x;
    252   delete x; // expected-warning{{Argument to 'delete' is uninitialized}}
    253   (*(volatile int *)0 = 1); // no warn
    254 }
    255 
    256 void testUninitDeleteArraySink() {
    257   int *x;
    258   delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}}
    259   (*(volatile int *)0 = 1); // no warn
    260 }
    261 
    262 namespace reference_count {
    263   class control_block {
    264     unsigned count;
    265   public:
    266     control_block() : count(0) {}
    267     void retain() { ++count; }
    268     int release() { return --count; }
    269   };
    270 
    271   template <typename T>
    272   class shared_ptr {
    273     T *p;
    274     control_block *control;
    275 
    276   public:
    277     shared_ptr() : p(0), control(0) {}
    278     explicit shared_ptr(T *p) : p(p), control(new control_block) {
    279       control->retain();
    280     }
    281     shared_ptr(shared_ptr &other) : p(other.p), control(other.control) {
    282       if (control)
    283           control->retain();
    284     }
    285     ~shared_ptr() {
    286       if (control && control->release() == 0) {
    287         delete p;
    288         delete control;
    289       }
    290     };
    291 
    292     T &operator *() {
    293       return *p;
    294     };
    295 
    296     void swap(shared_ptr &other) {
    297       T *tmp = p;
    298       p = other.p;
    299       other.p = tmp;
    300 
    301       control_block *ctrlTmp = control;
    302       control = other.control;
    303       other.control = ctrlTmp;
    304     }
    305   };
    306 
    307   void testSingle() {
    308     shared_ptr<int> a(new int);
    309     *a = 1;
    310   }
    311 
    312   void testDouble() {
    313     shared_ptr<int> a(new int);
    314     shared_ptr<int> b = a;
    315     *a = 1;
    316   }
    317 
    318   void testInvalidated() {
    319     shared_ptr<int> a(new int);
    320     shared_ptr<int> b = a;
    321     *a = 1;
    322 
    323     extern void use(shared_ptr<int> &);
    324     use(b);
    325   }
    326 
    327   void testNestedScope() {
    328     shared_ptr<int> a(new int);
    329     {
    330       shared_ptr<int> b = a;
    331     }
    332     *a = 1;
    333   }
    334 
    335   void testSwap() {
    336     shared_ptr<int> a(new int);
    337     shared_ptr<int> b;
    338     shared_ptr<int> c = a;
    339     shared_ptr<int>(c).swap(b);
    340   }
    341 
    342   void testUseAfterFree() {
    343     int *p = new int;
    344     {
    345       shared_ptr<int> a(p);
    346       shared_ptr<int> b = a;
    347     }
    348 
    349     // FIXME: We should get a warning here, but we don't because we've
    350     // conservatively modeled ~shared_ptr.
    351     *p = 1;
    352   }
    353 }
    354 
    355 // Test double delete
    356 class DerefClass{
    357 public:
    358   int *x;
    359   DerefClass() {}
    360   ~DerefClass() {*x = 1;}
    361 };
    362 
    363 void testDoubleDeleteClassInstance() {
    364   DerefClass *foo = new DerefClass();
    365   delete foo;
    366   delete foo; // expected-warning {{Attempt to delete released memory}}
    367 }
    368 
    369 class EmptyClass{
    370 public:
    371   EmptyClass() {}
    372   ~EmptyClass() {}
    373 };
    374 
    375 void testDoubleDeleteEmptyClass() {
    376   EmptyClass *foo = new EmptyClass();
    377   delete foo;
    378   delete foo;  // expected-warning {{Attempt to delete released memory}}
    379 }
    380