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