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