1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -verify -analyzer-config eagerly-assume=false %s
2 // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify -analyzer-config eagerly-assume=false %s
3 #include "Inputs/system-header-simulator-cxx.h"
4
5 void clang_analyzer_eval(bool);
6
7 typedef __typeof__(sizeof(int)) size_t;
8 extern "C" void *malloc(size_t);
9 extern "C" void free(void *);
10
11 int someGlobal;
12
13 class SomeClass {
14 public:
15 void f(int *p);
16 };
17
testImplicitlyDeclaredGlobalNew()18 void testImplicitlyDeclaredGlobalNew() {
19 if (someGlobal != 0)
20 return;
21
22 // This used to crash because the global operator new is being implicitly
23 // declared and it does not have a valid source location. (PR13090)
24 void *x = ::operator new(0);
25 ::operator delete(x);
26
27 // Check that the new/delete did not invalidate someGlobal;
28 clang_analyzer_eval(someGlobal == 0); // expected-warning{{TRUE}}
29 }
30
testPlacementNew()31 void *testPlacementNew() {
32 int *x = (int *)malloc(sizeof(int));
33 *x = 1;
34 clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};
35
36 void *y = new (x) int;
37 clang_analyzer_eval(x == y); // expected-warning{{TRUE}};
38 clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};
39
40 return y;
41 }
42
43 void *operator new(size_t, size_t, int *);
testCustomNew()44 void *testCustomNew() {
45 int x[1] = {1};
46 clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};
47
48 void *y = new (0, x) int;
49 clang_analyzer_eval(*x == 1); // expected-warning{{UNKNOWN}};
50
51 return y; // no-warning
52 }
53
54 void *operator new(size_t, void *, void *);
testCustomNewMalloc()55 void *testCustomNewMalloc() {
56 int *x = (int *)malloc(sizeof(int));
57
58 // Should be no-warning (the custom allocator could have freed x).
59 void *y = new (0, x) int; // no-warning
60
61 return y;
62 }
63
testScalarInitialization()64 void testScalarInitialization() {
65 int *n = new int(3);
66 clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}}
67
68 new (n) int();
69 clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}}
70
71 new (n) int{3};
72 clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}}
73
74 new (n) int{};
75 clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}}
76 }
77
78 struct PtrWrapper {
79 int *x;
80
PtrWrapperPtrWrapper81 PtrWrapper(int *input) : x(input) {}
82 };
83
testNewInvalidation()84 PtrWrapper *testNewInvalidation() {
85 // Ensure that we don't consider this a leak.
86 return new PtrWrapper(static_cast<int *>(malloc(4))); // no-warning
87 }
88
testNewInvalidationPlacement(PtrWrapper * w)89 void testNewInvalidationPlacement(PtrWrapper *w) {
90 // Ensure that we don't consider this a leak.
91 new (w) PtrWrapper(static_cast<int *>(malloc(4))); // no-warning
92 }
93
testNewInvalidationScalar()94 int **testNewInvalidationScalar() {
95 // Ensure that we don't consider this a leak.
96 return new (int *)(static_cast<int *>(malloc(4))); // no-warning
97 }
98
testNewInvalidationScalarPlacement(int ** p)99 void testNewInvalidationScalarPlacement(int **p) {
100 // Ensure that we don't consider this a leak.
101 new (p) (int *)(static_cast<int *>(malloc(4))); // no-warning
102 }
103
testCacheOut(PtrWrapper w)104 void testCacheOut(PtrWrapper w) {
105 extern bool coin();
106 if (coin())
107 w.x = 0;
108 new (&w.x) (int*)(0); // we cache out here; don't crash
109 }
110
testUseAfter(int * p)111 void testUseAfter(int *p) {
112 SomeClass *c = new SomeClass;
113 free(p);
114 c->f(p); // expected-warning{{Use of memory after it is freed}}
115 delete c;
116 }
117
118 // new/delete oparators are subjects of cplusplus.NewDelete.
testNewDeleteNoWarn()119 void testNewDeleteNoWarn() {
120 int i;
121 delete &i; // no-warning
122
123 int *p1 = new int;
124 delete ++p1; // no-warning
125
126 int *p2 = new int;
127 delete p2;
128 delete p2; // no-warning
129
130 int *p3 = new int; // no-warning
131 }
132
testDeleteMallocked()133 void testDeleteMallocked() {
134 int *x = (int *)malloc(sizeof(int));
135 // unix.MismatchedDeallocator would catch this, but we're not testing it here.
136 delete x;
137 }
138
testDeleteOpAfterFree()139 void testDeleteOpAfterFree() {
140 int *p = (int *)malloc(sizeof(int));
141 free(p);
142 operator delete(p); // expected-warning{{Use of memory after it is freed}}
143 }
144
testDeleteAfterFree()145 void testDeleteAfterFree() {
146 int *p = (int *)malloc(sizeof(int));
147 free(p);
148 delete p; // expected-warning{{Use of memory after it is freed}}
149 }
150
testStandardPlacementNewAfterFree()151 void testStandardPlacementNewAfterFree() {
152 int *p = (int *)malloc(sizeof(int));
153 free(p);
154 p = new(p) int; // expected-warning{{Use of memory after it is freed}}
155 }
156
testCustomPlacementNewAfterFree()157 void testCustomPlacementNewAfterFree() {
158 int *p = (int *)malloc(sizeof(int));
159 free(p);
160 p = new(0, p) int; // expected-warning{{Use of memory after it is freed}}
161 }
162
testUsingThisAfterDelete()163 void testUsingThisAfterDelete() {
164 SomeClass *c = new SomeClass;
165 delete c;
166 c->f(0); // no-warning
167 }
168
testAggregateNew()169 void testAggregateNew() {
170 struct Point { int x, y; };
171 new Point{1, 2}; // no crash
172
173 Point p;
174 new (&p) Point{1, 2}; // no crash
175 clang_analyzer_eval(p.x == 1); // expected-warning{{TRUE}}
176 clang_analyzer_eval(p.y == 2); // expected-warning{{TRUE}}
177 }
178
179 //--------------------------------
180 // Incorrectly-modelled behavior
181 //--------------------------------
182
testNoInitialization()183 int testNoInitialization() {
184 int *n = new int;
185
186 // Should warn that *n is uninitialized.
187 if (*n) { // no-warning
188 delete n;
189 return 0;
190 }
191 delete n;
192 return 1;
193 }
194
testNoInitializationPlacement()195 int testNoInitializationPlacement() {
196 int n;
197 new (&n) int;
198
199 if (n) { // expected-warning{{Branch condition evaluates to a garbage value}}
200 return 0;
201 }
202 return 1;
203 }
204
205 // Test modelling destructor call on call to delete
206 class IntPair{
207 public:
208 int x;
209 int y;
IntPair()210 IntPair() {};
~IntPair()211 ~IntPair() {x = x/y;}; //expected-warning {{Division by zero}}
212 };
213
testCallToDestructor()214 void testCallToDestructor() {
215 IntPair *b = new IntPair();
216 b->x = 1;
217 b->y = 0;
218 delete b; // This results in divide by zero in destructor
219 }
220
221 // Test Deleting a value that's passed as an argument.
222 class DerefClass{
223 public:
224 int *x;
DerefClass()225 DerefClass() {};
~DerefClass()226 ~DerefClass() {*x = 1;}; //expected-warning {{Dereference of null pointer (loaded from field 'x')}}
227 };
228
testDestCall(DerefClass * arg)229 void testDestCall(DerefClass *arg) {
230 delete arg;
231 }
232
test_delete_dtor_Arg()233 void test_delete_dtor_Arg() {
234 DerefClass *pair = new DerefClass();
235 pair->x = 0;
236 testDestCall(pair);
237 }
238
239 //Deleting the address of a local variable, null pointer
240 void abort(void) __attribute__((noreturn));
241
242 class NoReturnDtor {
243 public:
NoReturnDtor()244 NoReturnDtor() {}
~NoReturnDtor()245 ~NoReturnDtor() {abort();}
246 };
247
test_delete_dtor_LocalVar()248 void test_delete_dtor_LocalVar() {
249 NoReturnDtor test;
250 delete &test; // no warn or crash
251 }
252
253 class DerivedNoReturn:public NoReturnDtor {
254 public:
DerivedNoReturn()255 DerivedNoReturn() {};
~DerivedNoReturn()256 ~DerivedNoReturn() {};
257 };
258
testNullDtorDerived()259 void testNullDtorDerived() {
260 DerivedNoReturn *p = new DerivedNoReturn();
261 delete p; // Calls the base destructor which aborts, checked below
262 clang_analyzer_eval(true); // no warn
263 }
264
265 //Deleting a non-class pointer should not crash/warn
test_var_delete()266 void test_var_delete() {
267 int *v = new int;
268 delete v; // no crash/warn
269 clang_analyzer_eval(true); // expected-warning{{TRUE}}
270 }
271
test_array_delete()272 void test_array_delete() {
273 class C {
274 public:
275 ~C() {}
276 };
277
278 auto c1 = new C[2][3];
279 delete[] c1; // no-crash // no-warning
280
281 C c2[4];
282 // FIXME: Should warn.
283 delete[] &c2; // no-crash
284
285 C c3[7][6];
286 // FIXME: Should warn.
287 delete[] &c3; // no-crash
288 }
289
testDeleteNull()290 void testDeleteNull() {
291 NoReturnDtor *foo = 0;
292 delete foo; // should not call destructor, checked below
293 clang_analyzer_eval(true); // expected-warning{{TRUE}}
294 }
295
testNullAssigneddtor()296 void testNullAssigneddtor() {
297 NoReturnDtor *p = 0;
298 NoReturnDtor *s = p;
299 delete s; // should not call destructor, checked below
300 clang_analyzer_eval(true); // expected-warning{{TRUE}}
301 }
302
deleteArg(NoReturnDtor * test)303 void deleteArg(NoReturnDtor *test) {
304 delete test;
305 }
306
testNulldtorArg()307 void testNulldtorArg() {
308 NoReturnDtor *p = 0;
309 deleteArg(p);
310 clang_analyzer_eval(true); // expected-warning{{TRUE}}
311 }
312
testDeleteUnknown(NoReturnDtor * foo)313 void testDeleteUnknown(NoReturnDtor *foo) {
314 delete foo; // should assume non-null and call noreturn destructor
315 clang_analyzer_eval(true); // no-warning
316 }
317
testArrayNull()318 void testArrayNull() {
319 NoReturnDtor *fooArray = 0;
320 delete[] fooArray; // should not call destructor, checked below
321 clang_analyzer_eval(true); // expected-warning{{TRUE}}
322 }
323
testArrayDestr()324 void testArrayDestr() {
325 NoReturnDtor *p = new NoReturnDtor[2];
326 delete[] p; // Calls the base destructor which aborts, checked below
327 //TODO: clang_analyzer_eval should not be called
328 clang_analyzer_eval(true); // expected-warning{{TRUE}}
329 }
330
331 // Invalidate Region even in case of default destructor
332 class InvalidateDestTest {
333 public:
334 int x;
335 int *y;
336 ~InvalidateDestTest();
337 };
338
test_member_invalidation()339 int test_member_invalidation() {
340
341 //test invalidation of member variable
342 InvalidateDestTest *test = new InvalidateDestTest();
343 test->x = 5;
344 int *k = &(test->x);
345 clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}}
346 delete test;
347 clang_analyzer_eval(*k == 5); // expected-warning{{UNKNOWN}}
348
349 //test invalidation of member pointer
350 int localVar = 5;
351 test = new InvalidateDestTest();
352 test->y = &localVar;
353 delete test;
354 clang_analyzer_eval(localVar == 5); // expected-warning{{UNKNOWN}}
355
356 // Test aray elements are invalidated.
357 int Var1 = 5;
358 int Var2 = 5;
359 InvalidateDestTest *a = new InvalidateDestTest[2];
360 a[0].y = &Var1;
361 a[1].y = &Var2;
362 delete[] a;
363 clang_analyzer_eval(Var1 == 5); // expected-warning{{UNKNOWN}}
364 clang_analyzer_eval(Var2 == 5); // expected-warning{{UNKNOWN}}
365 return 0;
366 }
367