blob: 3384cfeb61417cc2e9394758d5102fad9f92a0aa [file] [log] [blame]
George Karpenkova393e682018-08-29 20:29:17 +00001// 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
Anton Yartsev13df0362013-03-25 01:35:45 +00003#include "Inputs/system-header-simulator-cxx.h"
Zhongxing Xu52c28fe2010-04-20 05:48:57 +00004
Jordan Rose44320362012-06-20 01:32:01 +00005void clang_analyzer_eval(bool);
6
Jordan Rose5089f3b2012-07-16 23:38:09 +00007typedef __typeof__(sizeof(int)) size_t;
Jordan Rose44320362012-06-20 01:32:01 +00008extern "C" void *malloc(size_t);
Anton Yartsev13df0362013-03-25 01:35:45 +00009extern "C" void free(void *);
Jordan Rose44320362012-06-20 01:32:01 +000010
Jordan Rose4688e602012-06-25 20:48:28 +000011int someGlobal;
Anton Yartsevcb2ccd62013-04-10 22:21:41 +000012
13class SomeClass {
14public:
15 void f(int *p);
16};
17
Jordan Rose4688e602012-06-25 20:48:28 +000018void 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
Jordan Rose44320362012-06-20 01:32:01 +000031void *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}};
Artem Dergacheva396df32018-01-24 20:59:40 +000038 clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};
Jordan Rose44320362012-06-20 01:32:01 +000039
40 return y;
41}
42
43void *operator new(size_t, size_t, int *);
44void *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
Zhongxing Xu52c28fe2010-04-20 05:48:57 +000052}
53
Jordan Rosea4ee0642012-07-02 22:21:47 +000054void *operator new(size_t, void *, void *);
55void *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
Jordan Rose5089f3b2012-07-16 23:38:09 +000064void 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
Jordan Rosec9318302012-08-27 17:50:07 +000078struct PtrWrapper {
79 int *x;
80
81 PtrWrapper(int *input) : x(input) {}
82};
83
84PtrWrapper *testNewInvalidation() {
85 // Ensure that we don't consider this a leak.
Jordan Rose3503cb32013-03-27 18:10:35 +000086 return new PtrWrapper(static_cast<int *>(malloc(4))); // no-warning
87}
88
89void 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
94int **testNewInvalidationScalar() {
95 // Ensure that we don't consider this a leak.
96 return new (int *)(static_cast<int *>(malloc(4))); // no-warning
97}
98
99void testNewInvalidationScalarPlacement(int **p) {
100 // Ensure that we don't consider this a leak.
101 new (p) (int *)(static_cast<int *>(malloc(4))); // no-warning
Jordan Rosec9318302012-08-27 17:50:07 +0000102}
103
Jordan Rose8f6b4b02013-03-30 01:31:42 +0000104void 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
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000111void 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}
Jordan Rose8f6b4b02013-03-30 01:31:42 +0000117
Anton Yartsev13df0362013-03-25 01:35:45 +0000118//--------------------------------------------------------------------
119// Check for intersection with other checkers from MallocChecker.cpp
120// bounded with unix.Malloc
121//--------------------------------------------------------------------
122
123// new/delete oparators are subjects of cplusplus.NewDelete.
124void testNewDeleteNoWarn() {
125 int i;
126 delete &i; // no-warning
127
128 int *p1 = new int;
129 delete ++p1; // no-warning
130
131 int *p2 = new int;
132 delete p2;
133 delete p2; // no-warning
134
135 int *p3 = new int; // no-warning
136}
137
138// unix.Malloc does not know about operators new/delete.
139void testDeleteMallocked() {
140 int *x = (int *)malloc(sizeof(int));
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +0000141 delete x; // FIXME: Should detect pointer escape and keep silent after 'delete' is modeled properly.
Anna Zaksa1de8562013-04-06 00:41:36 +0000142} // expected-warning{{Potential leak of memory pointed to by 'x'}}
Anton Yartsev13df0362013-03-25 01:35:45 +0000143
144void testDeleteOpAfterFree() {
145 int *p = (int *)malloc(sizeof(int));
146 free(p);
147 operator delete(p); // expected-warning{{Use of memory after it is freed}}
148}
149
150void testDeleteAfterFree() {
151 int *p = (int *)malloc(sizeof(int));
152 free(p);
153 delete p; // expected-warning{{Use of memory after it is freed}}
154}
155
156void testStandardPlacementNewAfterFree() {
157 int *p = (int *)malloc(sizeof(int));
158 free(p);
159 p = new(p) int; // expected-warning{{Use of memory after it is freed}}
160}
161
162void testCustomPlacementNewAfterFree() {
163 int *p = (int *)malloc(sizeof(int));
164 free(p);
165 p = new(0, p) int; // expected-warning{{Use of memory after it is freed}}
166}
Jordan Rosec9318302012-08-27 17:50:07 +0000167
Anton Yartsevcb2ccd62013-04-10 22:21:41 +0000168void testUsingThisAfterDelete() {
169 SomeClass *c = new SomeClass;
170 delete c;
171 c->f(0); // no-warning
172}
173
Jordan Rose64446532013-07-10 19:14:10 +0000174void testAggregateNew() {
175 struct Point { int x, y; };
176 new Point{1, 2}; // no crash
177
178 Point p;
179 new (&p) Point{1, 2}; // no crash
180 clang_analyzer_eval(p.x == 1); // expected-warning{{TRUE}}
181 clang_analyzer_eval(p.y == 2); // expected-warning{{TRUE}}
182}
183
Jordan Rose7d2bdd52012-06-20 05:34:32 +0000184//--------------------------------
185// Incorrectly-modelled behavior
186//--------------------------------
187
Jordan Rose5089f3b2012-07-16 23:38:09 +0000188int testNoInitialization() {
Jordan Rose7d2bdd52012-06-20 05:34:32 +0000189 int *n = new int;
190
191 // Should warn that *n is uninitialized.
192 if (*n) { // no-warning
Anton Yartsev13df0362013-03-25 01:35:45 +0000193 delete n;
Jordan Rose5089f3b2012-07-16 23:38:09 +0000194 return 0;
Jordan Rose7d2bdd52012-06-20 05:34:32 +0000195 }
Anton Yartsev13df0362013-03-25 01:35:45 +0000196 delete n;
Jordan Rose5089f3b2012-07-16 23:38:09 +0000197 return 1;
Jordan Rose7d2bdd52012-06-20 05:34:32 +0000198}
199
Jordan Rose5089f3b2012-07-16 23:38:09 +0000200int testNoInitializationPlacement() {
201 int n;
202 new (&n) int;
Jordan Rose7d2bdd52012-06-20 05:34:32 +0000203
Artem Dergacheva396df32018-01-24 20:59:40 +0000204 if (n) { // expected-warning{{Branch condition evaluates to a garbage value}}
Jordan Rose5089f3b2012-07-16 23:38:09 +0000205 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
Artem Dergachev4fbd97e2018-04-27 02:16:03 +0000277void test_array_delete() {
278 class C {
279 public:
280 ~C() {}
281 };
282
283 auto c1 = new C[2][3];
284 delete[] c1; // no-crash // no-warning
285
286 C c2[4];
287 // FIXME: Should warn.
288 delete[] &c2; // no-crash
289
290 C c3[7][6];
291 // FIXME: Should warn.
292 delete[] &c3; // no-crash
293}
294
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000295void testDeleteNull() {
296 NoReturnDtor *foo = 0;
297 delete foo; // should not call destructor, checked below
298 clang_analyzer_eval(true); // expected-warning{{TRUE}}
299}
300
301void testNullAssigneddtor() {
302 NoReturnDtor *p = 0;
303 NoReturnDtor *s = p;
304 delete s; // should not call destructor, checked below
305 clang_analyzer_eval(true); // expected-warning{{TRUE}}
306}
307
308void deleteArg(NoReturnDtor *test) {
309 delete test;
310}
311
312void testNulldtorArg() {
313 NoReturnDtor *p = 0;
314 deleteArg(p);
315 clang_analyzer_eval(true); // expected-warning{{TRUE}}
316}
317
318void testDeleteUnknown(NoReturnDtor *foo) {
319 delete foo; // should assume non-null and call noreturn destructor
320 clang_analyzer_eval(true); // no-warning
321}
322
323void testArrayNull() {
324 NoReturnDtor *fooArray = 0;
325 delete[] fooArray; // should not call destructor, checked below
326 clang_analyzer_eval(true); // expected-warning{{TRUE}}
327}
328
329void testArrayDestr() {
330 NoReturnDtor *p = new NoReturnDtor[2];
331 delete[] p; // Calls the base destructor which aborts, checked below
Artem Dergachev168e29f2018-02-15 02:51:58 +0000332 //TODO: clang_analyzer_eval should not be called
333 clang_analyzer_eval(true); // expected-warning{{TRUE}}
Jordan Rose1ccc43d2013-09-25 16:06:17 +0000334}
335
336// Invalidate Region even in case of default destructor
337class InvalidateDestTest {
338public:
339 int x;
340 int *y;
341 ~InvalidateDestTest();
342};
343
344int test_member_invalidation() {
345
346 //test invalidation of member variable
347 InvalidateDestTest *test = new InvalidateDestTest();
348 test->x = 5;
349 int *k = &(test->x);
350 clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}}
351 delete test;
352 clang_analyzer_eval(*k == 5); // expected-warning{{UNKNOWN}}
353
354 //test invalidation of member pointer
355 int localVar = 5;
356 test = new InvalidateDestTest();
357 test->y = &localVar;
358 delete test;
359 clang_analyzer_eval(localVar == 5); // expected-warning{{UNKNOWN}}
360
361 // Test aray elements are invalidated.
362 int Var1 = 5;
363 int Var2 = 5;
364 InvalidateDestTest *a = new InvalidateDestTest[2];
365 a[0].y = &Var1;
366 a[1].y = &Var2;
367 delete[] a;
368 clang_analyzer_eval(Var1 == 5); // expected-warning{{UNKNOWN}}
369 clang_analyzer_eval(Var2 == 5); // expected-warning{{UNKNOWN}}
370 return 0;
371}