1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -verify %s
2 #include "Inputs/system-header-simulator-cxx.h"
3
4 void clang_analyzer_eval(bool);
5
6 typedef __typeof__(sizeof(int)) size_t;
7 extern "C" void *malloc(size_t);
8 extern "C" void free(void *);
9
10 int someGlobal;
11
12 class SomeClass {
13 public:
14 void f(int *p);
15 };
16
testImplicitlyDeclaredGlobalNew()17 void 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
testPlacementNew()30 void *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
42 void *operator new(size_t, size_t, int *);
testCustomNew()43 void *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
51 }
52
53 void *operator new(size_t, void *, void *);
testCustomNewMalloc()54 void *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
testScalarInitialization()63 void 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
77 struct PtrWrapper {
78 int *x;
79
PtrWrapperPtrWrapper80 PtrWrapper(int *input) : x(input) {}
81 };
82
testNewInvalidation()83 PtrWrapper *testNewInvalidation() {
84 // Ensure that we don't consider this a leak.
85 return new PtrWrapper(static_cast<int *>(malloc(4))); // no-warning
86 }
87
testNewInvalidationPlacement(PtrWrapper * w)88 void 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
testNewInvalidationScalar()93 int **testNewInvalidationScalar() {
94 // Ensure that we don't consider this a leak.
95 return new (int *)(static_cast<int *>(malloc(4))); // no-warning
96 }
97
testNewInvalidationScalarPlacement(int ** p)98 void testNewInvalidationScalarPlacement(int **p) {
99 // Ensure that we don't consider this a leak.
100 new (p) (int *)(static_cast<int *>(malloc(4))); // no-warning
101 }
102
testCacheOut(PtrWrapper w)103 void 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
testUseAfter(int * p)110 void 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 }
116
117 //--------------------------------------------------------------------
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.
testNewDeleteNoWarn()123 void 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.
testDeleteMallocked()138 void testDeleteMallocked() {
139 int *x = (int *)malloc(sizeof(int));
140 delete x; // FIXME: Shoud detect pointer escape and keep silent after 'delete' is modeled properly.
141 } // expected-warning{{Potential leak of memory pointed to by 'x'}}
142
testDeleteOpAfterFree()143 void 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
testDeleteAfterFree()149 void 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
testStandardPlacementNewAfterFree()155 void 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
testCustomPlacementNewAfterFree()161 void 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 }
166
testUsingThisAfterDelete()167 void testUsingThisAfterDelete() {
168 SomeClass *c = new SomeClass;
169 delete c;
170 c->f(0); // no-warning
171 }
172
testAggregateNew()173 void 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
183 //--------------------------------
184 // Incorrectly-modelled behavior
185 //--------------------------------
186
testNoInitialization()187 int testNoInitialization() {
188 int *n = new int;
189
190 // Should warn that *n is uninitialized.
191 if (*n) { // no-warning
192 delete n;
193 return 0;
194 }
195 delete n;
196 return 1;
197 }
198
testNoInitializationPlacement()199 int testNoInitializationPlacement() {
200 int n;
201 new (&n) int;
202
203 // Should warn that n is uninitialized.
204 if (n) { // no-warning
205 return 0;
206 }
207 return 1;
208 }
209
210 // Test modelling destructor call on call to delete
211 class IntPair{
212 public:
213 int x;
214 int y;
IntPair()215 IntPair() {};
~IntPair()216 ~IntPair() {x = x/y;}; //expected-warning {{Division by zero}}
217 };
218
testCallToDestructor()219 void 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.
227 class DerefClass{
228 public:
229 int *x;
DerefClass()230 DerefClass() {};
~DerefClass()231 ~DerefClass() {*x = 1;}; //expected-warning {{Dereference of null pointer (loaded from field 'x')}}
232 };
233
testDestCall(DerefClass * arg)234 void testDestCall(DerefClass *arg) {
235 delete arg;
236 }
237
test_delete_dtor_Arg()238 void 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
245 void abort(void) __attribute__((noreturn));
246
247 class NoReturnDtor {
248 public:
NoReturnDtor()249 NoReturnDtor() {}
~NoReturnDtor()250 ~NoReturnDtor() {abort();}
251 };
252
test_delete_dtor_LocalVar()253 void test_delete_dtor_LocalVar() {
254 NoReturnDtor test;
255 delete &test; // no warn or crash
256 }
257
258 class DerivedNoReturn:public NoReturnDtor {
259 public:
DerivedNoReturn()260 DerivedNoReturn() {};
~DerivedNoReturn()261 ~DerivedNoReturn() {};
262 };
263
testNullDtorDerived()264 void 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
270 //Deleting a non-class pointer should not crash/warn
test_var_delete()271 void test_var_delete() {
272 int *v = new int;
273 delete v; // no crash/warn
274 clang_analyzer_eval(true); // expected-warning{{TRUE}}
275 }
276
testDeleteNull()277 void testDeleteNull() {
278 NoReturnDtor *foo = 0;
279 delete foo; // should not call destructor, checked below
280 clang_analyzer_eval(true); // expected-warning{{TRUE}}
281 }
282
testNullAssigneddtor()283 void 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
deleteArg(NoReturnDtor * test)290 void deleteArg(NoReturnDtor *test) {
291 delete test;
292 }
293
testNulldtorArg()294 void testNulldtorArg() {
295 NoReturnDtor *p = 0;
296 deleteArg(p);
297 clang_analyzer_eval(true); // expected-warning{{TRUE}}
298 }
299
testDeleteUnknown(NoReturnDtor * foo)300 void testDeleteUnknown(NoReturnDtor *foo) {
301 delete foo; // should assume non-null and call noreturn destructor
302 clang_analyzer_eval(true); // no-warning
303 }
304
testArrayNull()305 void testArrayNull() {
306 NoReturnDtor *fooArray = 0;
307 delete[] fooArray; // should not call destructor, checked below
308 clang_analyzer_eval(true); // expected-warning{{TRUE}}
309 }
310
testArrayDestr()311 void 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
319 class InvalidateDestTest {
320 public:
321 int x;
322 int *y;
323 ~InvalidateDestTest();
324 };
325
test_member_invalidation()326 int 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 }
354