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