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