• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
testGlobalOpNew()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 
testGlobalOpNewArray()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 
testGlobalNewExpr()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 
testGlobalNewExprArray()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
testGlobalNoThrowPlacementOpNewBeforeOverload()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 
testGlobalNoThrowPlacementExprNewBeforeOverload()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
testGlobalPointerPlacementNew()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
testNewMemoryIsInHeap()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 
PtrWrapperPtrWrapper82   PtrWrapper(int *input) : x(input) {}
83 };
84 
testNewInvalidationPlacement(PtrWrapper * w)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 
testUseZeroAlloc1()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 
testUseZeroAlloc2()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 
testUseZeroAlloc3()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 
testUseFirstArgAfterDelete()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 
testUseMiddleArgAfterDelete(int * p)132 void testUseMiddleArgAfterDelete(int *p) {
133   delete p;
134   f(0, p); // expected-warning{{Use of memory after it is freed}}
135 }
136 
testUseLastArgAfterDelete(int * p)137 void testUseLastArgAfterDelete(int *p) {
138   delete p;
139   f(0, 0, p); // expected-warning{{Use of memory after it is freed}}
140 }
141 
testUseSeveralArgsAfterDelete(int * p)142 void testUseSeveralArgsAfterDelete(int *p) {
143   delete p;
144   f(p, p, p); // expected-warning{{Use of memory after it is freed}}
145 }
146 
testUseRefArgAfterDelete(SomeClass & c)147 void testUseRefArgAfterDelete(SomeClass &c) {
148   delete &c;
149   g(c); // expected-warning{{Use of memory after it is freed}}
150 }
151 
testVariadicArgAfterDelete()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 
testUseMethodArgAfterDelete(int * p)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 
testUseThisAfterDelete()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 
testDoubleDelete()171 void testDoubleDelete() {
172   int *p = new int;
173   delete p;
174   delete p; // expected-warning{{Attempt to free released memory}}
175 }
176 
testExprDeleteArg()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 
testExprDeleteArrArg()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 
testAllocDeallocNames()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 
testConstEscape()203 void testConstEscape() {
204   int *p = new int(1);
205   escape(*p);
206 } // no-warning
207 
testConstEscapeStruct()208 void testConstEscapeStruct() {
209   StWithConstPtr *St = new StWithConstPtr();
210   escapeStruct(*St);
211 } // no-warning
212 
testConstEscapeStructPtr()213 void testConstEscapeStructPtr() {
214   StWithConstPtr *St = new StWithConstPtr();
215   escapePtr(St);
216 } // no-warning
217 
testConstEscapeMember()218 void testConstEscapeMember() {
219   StWithConstPtr St;
220   St.memp = new int(2);
221   escapeVoidPtr(St.memp);
222 } // no-warning
223 
testConstEscapePlacementNew()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[]========================
testUninitDelete()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 
testUninitDeleteArray()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 
testUninitFree()245 void testUninitFree() {
246   int *x;
247   free(x); // expected-warning{{Function call argument is an uninitialized value}}
248 }
249 
testUninitDeleteSink()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 
testUninitDeleteArraySink()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:
control_block()266     control_block() : count(0) {}
retain()267     void retain() { ++count; }
release()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:
shared_ptr()277     shared_ptr() : p(0), control(0) {}
shared_ptr(T * p)278     explicit shared_ptr(T *p) : p(p), control(new control_block) {
279       control->retain();
280     }
shared_ptr(shared_ptr & other)281     shared_ptr(shared_ptr &other) : p(other.p), control(other.control) {
282       if (control)
283           control->retain();
284     }
~shared_ptr()285     ~shared_ptr() {
286       if (control && control->release() == 0) {
287         delete p;
288         delete control;
289       }
290     };
291 
operator *()292     T &operator *() {
293       return *p;
294     };
295 
swap(shared_ptr & other)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 
testSingle()307   void testSingle() {
308     shared_ptr<int> a(new int);
309     *a = 1;
310   }
311 
testDouble()312   void testDouble() {
313     shared_ptr<int> a(new int);
314     shared_ptr<int> b = a;
315     *a = 1;
316   }
317 
testInvalidated()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 
testNestedScope()327   void testNestedScope() {
328     shared_ptr<int> a(new int);
329     {
330       shared_ptr<int> b = a;
331     }
332     *a = 1;
333   }
334 
testSwap()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 
testUseAfterFree()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;
DerefClass()359   DerefClass() {}
~DerefClass()360   ~DerefClass() {*x = 1;}
361 };
362 
testDoubleDeleteClassInstance()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:
EmptyClass()371   EmptyClass() {}
~EmptyClass()372   ~EmptyClass() {}
373 };
374 
testDoubleDeleteEmptyClass()375 void testDoubleDeleteEmptyClass() {
376   EmptyClass *foo = new EmptyClass();
377   delete foo;
378   delete foo;  // expected-warning {{Attempt to delete released memory}}
379 }
380