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