blob: 6cfcb1d92719534203d1d43ce6207dc42a30e6b1 [file] [log] [blame]
Dominic Chen184c6242017-03-03 18:02:02 +00001// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -verify %s
Anton Yartsev13df0362013-03-25 01:35:45 +00002#include "Inputs/system-header-simulator-cxx.h"
Zhongxing Xu52c28fe2010-04-20 05:48:57 +00003
Jordan Rose44320362012-06-20 01:32:01 +00004void clang_analyzer_eval(bool);
5
Jordan Rose5089f3b2012-07-16 23:38:09 +00006typedef __typeof__(sizeof(int)) size_t;
Jordan Rose44320362012-06-20 01:32:01 +00007extern "C" void *malloc(size_t);
Anton Yartsev13df0362013-03-25 01:35:45 +00008extern "C" void free(void *);
Jordan Rose44320362012-06-20 01:32:01 +00009
Jordan Rose4688e602012-06-25 20:48:28 +000010int someGlobal;
Anton Yartsevcb2ccd62013-04-10 22:21:41 +000011
12class SomeClass {
13public:
14 void f(int *p);
15};
16
Jordan Rose4688e602012-06-25 20:48:28 +000017void testImplicitlyDeclaredGlobalNew() {
18 if (someGlobal != 0)
19 return;
20
21 // This used to crash because the global operator new is being implicitly
22 // declared and it does not have a valid source location. (PR13090)
23 void *x = ::operator new(0);
24 ::operator delete(x);
25
26 // Check that the new/delete did not invalidate someGlobal;
27 clang_analyzer_eval(someGlobal == 0); // expected-warning{{TRUE}}
28}
29
Jordan Rose44320362012-06-20 01:32:01 +000030void *testPlacementNew() {
31 int *x = (int *)malloc(sizeof(int));
32 *x = 1;
33 clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};
34
35 void *y = new (x) int;
36 clang_analyzer_eval(x == y); // expected-warning{{TRUE}};
37 clang_analyzer_eval(*x == 1); // expected-warning{{UNKNOWN}};
38
39 return y;
40}
41
42void *operator new(size_t, size_t, int *);
43void *testCustomNew() {
44 int x[1] = {1};
45 clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};
46
47 void *y = new (0, x) int;
48 clang_analyzer_eval(*x == 1); // expected-warning{{UNKNOWN}};
49
50 return y; // no-warning
Zhongxing Xu52c28fe2010-04-20 05:48:57 +000051}
52
Jordan Rosea4ee0642012-07-02 22:21:47 +000053void *operator new(size_t, void *, void *);
54void *testCustomNewMalloc() {
55 int *x = (int *)malloc(sizeof(int));
56
57 // Should be no-warning (the custom allocator could have freed x).
58 void *y = new (0, x) int; // no-warning
59
60 return y;
61}
62
Jordan Rose5089f3b2012-07-16 23:38:09 +000063void testScalarInitialization() {
64 int *n = new int(3);
65 clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}}
66
67 new (n) int();
68 clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}}
69
70 new (n) int{3};
71 clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}}
72
73 new (n) int{};
74 clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}}
75}
76
Jordan Rosec9318302012-08-27 17:50:07 +000077struct PtrWrapper {
78 int *x;
79
80 PtrWrapper(int *input) : x(input) {}
81};
82
83PtrWrapper *testNewInvalidation() {
84 // Ensure that we don't consider this a leak.
Jordan Rose3503cb32013-03-27 18:10:35 +000085 return new PtrWrapper(static_cast<int *>(malloc(4))); // no-warning
86}
87
88void testNewInvalidationPlacement(PtrWrapper *w) {
89 // Ensure that we don't consider this a leak.
90 new (w) PtrWrapper(static_cast<int *>(malloc(4))); // no-warning
91}
92
93int **testNewInvalidationScalar() {
94 // Ensure that we don't consider this a leak.
95 return new (int *)(static_cast<int *>(malloc(4))); // no-warning
96}
97
98void testNewInvalidationScalarPlacement(int **p) {
99 // Ensure that we don't consider this a leak.
100 new (p) (int *)(static_cast<int *>(malloc(4))); // no-warning
Jordan Rosec9318302012-08-27 17:50:07 +0000101}
102
Jordan Rose8f6b4b02013-03-30 01:31:42 +0000103void testCacheOut(PtrWrapper w) {
104 extern bool coin();
105 if (coin())
106 w.x = 0;
107 new (&w.x) (int*)(0); // we cache out here; don't crash
108}
109
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000110void testUseAfter(int *p) {
111 SomeClass *c = new SomeClass;
112 free(p);
113 c->f(p); // expected-warning{{Use of memory after it is freed}}
114 delete c;
115}
Jordan Rose8f6b4b02013-03-30 01:31:42 +0000116
Anton Yartsev13df0362013-03-25 01:35:45 +0000117//--------------------------------------------------------------------
118// Check for intersection with other checkers from MallocChecker.cpp
119// bounded with unix.Malloc
120//--------------------------------------------------------------------
121
122// new/delete oparators are subjects of cplusplus.NewDelete.
123void testNewDeleteNoWarn() {
124 int i;
125 delete &i; // no-warning
126
127 int *p1 = new int;
128 delete ++p1; // no-warning
129
130 int *p2 = new int;
131 delete p2;
132 delete p2; // no-warning
133
134 int *p3 = new int; // no-warning
135}
136
137// unix.Malloc does not know about operators new/delete.
138void testDeleteMallocked() {
139 int *x = (int *)malloc(sizeof(int));
140 delete x; // FIXME: Shoud detect pointer escape and keep silent after 'delete' is modeled properly.
Anna Zaksa1de8562013-04-06 00:41:36 +0000141} // expected-warning{{Potential leak of memory pointed to by 'x'}}
Anton Yartsev13df0362013-03-25 01:35:45 +0000142
143void testDeleteOpAfterFree() {
144 int *p = (int *)malloc(sizeof(int));
145 free(p);
146 operator delete(p); // expected-warning{{Use of memory after it is freed}}
147}
148
149void testDeleteAfterFree() {
150 int *p = (int *)malloc(sizeof(int));
151 free(p);
152 delete p; // expected-warning{{Use of memory after it is freed}}
153}
154
155void testStandardPlacementNewAfterFree() {
156 int *p = (int *)malloc(sizeof(int));
157 free(p);
158 p = new(p) int; // expected-warning{{Use of memory after it is freed}}
159}
160
161void testCustomPlacementNewAfterFree() {
162 int *p = (int *)malloc(sizeof(int));
163 free(p);
164 p = new(0, p) int; // expected-warning{{Use of memory after it is freed}}
165}
Jordan Rosec9318302012-08-27 17:50:07 +0000166
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000167void testUsingThisAfterDelete() {
168 SomeClass *c = new SomeClass;
169 delete c;
170 c->f(0); // no-warning
171}
172
Jordan Rose64446532013-07-10 19:14:10 +0000173void testAggregateNew() {
174 struct Point { int x, y; };
175 new Point{1, 2}; // no crash
176
177 Point p;
178 new (&p) Point{1, 2}; // no crash
179 clang_analyzer_eval(p.x == 1); // expected-warning{{TRUE}}
180 clang_analyzer_eval(p.y == 2); // expected-warning{{TRUE}}
181}
182
Jordan Rose7d2bdd52012-06-20 05:34:32 +0000183//--------------------------------
184// Incorrectly-modelled behavior
185//--------------------------------
186
Jordan Rose5089f3b2012-07-16 23:38:09 +0000187int testNoInitialization() {
Jordan Rose7d2bdd52012-06-20 05:34:32 +0000188 int *n = new int;
189
190 // Should warn that *n is uninitialized.
191 if (*n) { // no-warning
Anton Yartsev13df0362013-03-25 01:35:45 +0000192 delete n;
Jordan Rose5089f3b2012-07-16 23:38:09 +0000193 return 0;
Jordan Rose7d2bdd52012-06-20 05:34:32 +0000194 }
Anton Yartsev13df0362013-03-25 01:35:45 +0000195 delete n;
Jordan Rose5089f3b2012-07-16 23:38:09 +0000196 return 1;
Jordan Rose7d2bdd52012-06-20 05:34:32 +0000197}
198
Jordan Rose5089f3b2012-07-16 23:38:09 +0000199int testNoInitializationPlacement() {
200 int n;
201 new (&n) int;
Jordan Rose7d2bdd52012-06-20 05:34:32 +0000202
Jordan Rose5089f3b2012-07-16 23:38:09 +0000203 // Should warn that n is uninitialized.
204 if (n) { // no-warning
205 return 0;
206 }
207 return 1;
Jordan Rose7d2bdd52012-06-20 05:34:32 +0000208}
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000209
210// Test modelling destructor call on call to delete
211class IntPair{
212public:
213 int x;
214 int y;
215 IntPair() {};
216 ~IntPair() {x = x/y;}; //expected-warning {{Division by zero}}
217};
218
219void testCallToDestructor() {
220 IntPair *b = new IntPair();
221 b->x = 1;
222 b->y = 0;
223 delete b; // This results in divide by zero in destructor
224}
225
226// Test Deleting a value that's passed as an argument.
227class DerefClass{
228public:
229 int *x;
230 DerefClass() {};
231 ~DerefClass() {*x = 1;}; //expected-warning {{Dereference of null pointer (loaded from field 'x')}}
232};
233
234void testDestCall(DerefClass *arg) {
235 delete arg;
236}
237
238void test_delete_dtor_Arg() {
239 DerefClass *pair = new DerefClass();
240 pair->x = 0;
241 testDestCall(pair);
242}
243
244//Deleting the address of a local variable, null pointer
245void abort(void) __attribute__((noreturn));
246
247class NoReturnDtor {
248public:
249 NoReturnDtor() {}
250 ~NoReturnDtor() {abort();}
251};
252
253void test_delete_dtor_LocalVar() {
254 NoReturnDtor test;
255 delete &test; // no warn or crash
256}
257
258class DerivedNoReturn:public NoReturnDtor {
259public:
260 DerivedNoReturn() {};
261 ~DerivedNoReturn() {};
262};
263
264void testNullDtorDerived() {
265 DerivedNoReturn *p = new DerivedNoReturn();
266 delete p; // Calls the base destructor which aborts, checked below
267 clang_analyzer_eval(true); // no warn
268}
269
Alp Tokerd4733632013-12-05 04:47:09 +0000270//Deleting a non-class pointer should not crash/warn
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000271void test_var_delete() {
272 int *v = new int;
273 delete v; // no crash/warn
274 clang_analyzer_eval(true); // expected-warning{{TRUE}}
275}
276
277void testDeleteNull() {
278 NoReturnDtor *foo = 0;
279 delete foo; // should not call destructor, checked below
280 clang_analyzer_eval(true); // expected-warning{{TRUE}}
281}
282
283void testNullAssigneddtor() {
284 NoReturnDtor *p = 0;
285 NoReturnDtor *s = p;
286 delete s; // should not call destructor, checked below
287 clang_analyzer_eval(true); // expected-warning{{TRUE}}
288}
289
290void deleteArg(NoReturnDtor *test) {
291 delete test;
292}
293
294void testNulldtorArg() {
295 NoReturnDtor *p = 0;
296 deleteArg(p);
297 clang_analyzer_eval(true); // expected-warning{{TRUE}}
298}
299
300void testDeleteUnknown(NoReturnDtor *foo) {
301 delete foo; // should assume non-null and call noreturn destructor
302 clang_analyzer_eval(true); // no-warning
303}
304
305void testArrayNull() {
306 NoReturnDtor *fooArray = 0;
307 delete[] fooArray; // should not call destructor, checked below
308 clang_analyzer_eval(true); // expected-warning{{TRUE}}
309}
310
311void testArrayDestr() {
312 NoReturnDtor *p = new NoReturnDtor[2];
313 delete[] p; // Calls the base destructor which aborts, checked below
314 //TODO: clang_analyzer_eval should not be called
315 clang_analyzer_eval(true); // expected-warning{{TRUE}}
316}
317
318// Invalidate Region even in case of default destructor
319class InvalidateDestTest {
320public:
321 int x;
322 int *y;
323 ~InvalidateDestTest();
324};
325
326int test_member_invalidation() {
327
328 //test invalidation of member variable
329 InvalidateDestTest *test = new InvalidateDestTest();
330 test->x = 5;
331 int *k = &(test->x);
332 clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}}
333 delete test;
334 clang_analyzer_eval(*k == 5); // expected-warning{{UNKNOWN}}
335
336 //test invalidation of member pointer
337 int localVar = 5;
338 test = new InvalidateDestTest();
339 test->y = &localVar;
340 delete test;
341 clang_analyzer_eval(localVar == 5); // expected-warning{{UNKNOWN}}
342
343 // Test aray elements are invalidated.
344 int Var1 = 5;
345 int Var2 = 5;
346 InvalidateDestTest *a = new InvalidateDestTest[2];
347 a[0].y = &Var1;
348 a[1].y = &Var2;
349 delete[] a;
350 clang_analyzer_eval(Var1 == 5); // expected-warning{{UNKNOWN}}
351 clang_analyzer_eval(Var2 == 5); // expected-warning{{UNKNOWN}}
352 return 0;
353}