xref: /llvm-project/clang/test/Analysis/new.cpp (revision a504ddc8bf9d5c406ea88b84b8495d7aae200d4c)
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -std=c++11 -verify -analyzer-config eagerly-assume=false %s
2 // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -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 void clang_analyzer_warnIfReached();
7 
8 typedef __typeof__(sizeof(int)) size_t;
9 extern "C" void *malloc(size_t);
10 extern "C" void free(void *);
11 
12 int someGlobal;
13 
14 class SomeClass {
15 public:
16   void f(int *p);
17 };
18 
testImplicitlyDeclaredGlobalNew()19 void testImplicitlyDeclaredGlobalNew() {
20   if (someGlobal != 0)
21     return;
22 
23   // This used to crash because the global operator new is being implicitly
24   // declared and it does not have a valid source location. (PR13090)
25   void *x = ::operator new(0);
26   ::operator delete(x);
27 
28   // Check that the new/delete did not invalidate someGlobal;
29   clang_analyzer_eval(someGlobal == 0); // expected-warning{{TRUE}}
30 }
31 
testPlacementNew()32 void *testPlacementNew() {
33   int *x = (int *)malloc(sizeof(int));
34   *x = 1;
35   clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};
36 
37   void *y = new (x) int;
38   clang_analyzer_eval(x == y); // expected-warning{{TRUE}};
39   clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};
40 
41   return y;
42 }
43 
44 void *operator new(size_t, size_t, int *);
testCustomNew()45 void *testCustomNew() {
46   int x[1] = {1};
47   clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};
48 
49   void *y = new (0, x) int;
50   clang_analyzer_eval(*x == 1); // expected-warning{{UNKNOWN}};
51 
52   return y; // no-warning
53 }
54 
55 void *operator new(size_t, void *, void *);
testCustomNewMalloc()56 void *testCustomNewMalloc() {
57   int *x = (int *)malloc(sizeof(int));
58 
59   // Should be no-warning (the custom allocator could have freed x).
60   void *y = new (0, x) int; // no-warning
61 
62   return y;
63 }
64 
testScalarInitialization()65 void testScalarInitialization() {
66   int *n = new int(3);
67   clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}}
68 
69   new (n) int();
70   clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}}
71 
72   new (n) int{3};
73   clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}}
74 
75   new (n) int{};
76   clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}}
77 }
78 
79 struct PtrWrapper {
80   int *x;
81 
PtrWrapperPtrWrapper82   PtrWrapper(int *input) : x(input) {}
83 };
84 
testNewInvalidation()85 PtrWrapper *testNewInvalidation() {
86   // Ensure that we don't consider this a leak.
87   return new PtrWrapper(static_cast<int *>(malloc(4))); // no-warning
88 }
89 
testNewInvalidationPlacement(PtrWrapper * w)90 void testNewInvalidationPlacement(PtrWrapper *w) {
91   // Ensure that we don't consider this a leak.
92   new (w) PtrWrapper(static_cast<int *>(malloc(4))); // no-warning
93 }
94 
testNewInvalidationScalar()95 int **testNewInvalidationScalar() {
96   // Ensure that we don't consider this a leak.
97   return new (int *)(static_cast<int *>(malloc(4))); // no-warning
98 }
99 
testNewInvalidationScalarPlacement(int ** p)100 void testNewInvalidationScalarPlacement(int **p) {
101   // Ensure that we don't consider this a leak.
102   new (p) (int *)(static_cast<int *>(malloc(4))); // no-warning
103 }
104 
testCacheOut(PtrWrapper w)105 void testCacheOut(PtrWrapper w) {
106   extern bool coin();
107   if (coin())
108     w.x = 0;
109   new (&w.x) (int*)(0); // we cache out here; don't crash
110 }
111 
testUseAfter(int * p)112 void testUseAfter(int *p) {
113   SomeClass *c = new SomeClass;
114   free(p);
115   c->f(p); // expected-warning{{Use of memory after it is freed}}
116   delete c;
117 }
118 
119 // new/delete oparators are subjects of cplusplus.NewDelete.
testNewDeleteNoWarn()120 void testNewDeleteNoWarn() {
121   int i;
122   delete &i; // no-warning
123 
124   int *p1 = new int;
125   delete ++p1; // no-warning
126 
127   int *p2 = new int;
128   delete p2;
129   delete p2; // no-warning
130 
131   int *p3 = new int; // no-warning
132 }
133 
testDeleteMallocked()134 void testDeleteMallocked() {
135   int *x = (int *)malloc(sizeof(int));
136   // unix.MismatchedDeallocator would catch this, but we're not testing it here.
137   delete x;
138 }
139 
testDeleteOpAfterFree()140 void testDeleteOpAfterFree() {
141   int *p = (int *)malloc(sizeof(int));
142   free(p);
143   operator delete(p); // expected-warning{{Use of memory after it is freed}}
144 }
145 
testDeleteAfterFree()146 void testDeleteAfterFree() {
147   int *p = (int *)malloc(sizeof(int));
148   free(p);
149   delete p; // expected-warning{{Use of memory after it is freed}}
150 }
151 
testStandardPlacementNewAfterFree()152 void testStandardPlacementNewAfterFree() {
153   int *p = (int *)malloc(sizeof(int));
154   free(p);
155   p = new(p) int; // expected-warning{{Use of memory after it is freed}}
156 }
157 
testCustomPlacementNewAfterFree()158 void testCustomPlacementNewAfterFree() {
159   int *p = (int *)malloc(sizeof(int));
160   free(p);
161   p = new(0, p) int; // expected-warning{{Use of memory after it is freed}}
162 }
163 
testUsingThisAfterDelete()164 void testUsingThisAfterDelete() {
165   SomeClass *c = new SomeClass;
166   delete c;
167   c->f(0); // no-warning
168 }
169 
testAggregateNew()170 void testAggregateNew() {
171   struct Point { int x, y; };
172   new Point{1, 2}; // no crash
173 
174   Point p;
175   new (&p) Point{1, 2}; // no crash
176   clang_analyzer_eval(p.x == 1); // expected-warning{{TRUE}}
177   clang_analyzer_eval(p.y == 2); // expected-warning{{TRUE}}
178 }
179 
testNoInitialization()180 int testNoInitialization() {
181   int *n = new int;
182 
183   if (*n) { // expected-warning{{Branch condition evaluates to a garbage value [core.uninitialized.Branch]}}
184     delete n;
185     return 0;
186   }
187   delete n;
188   return 1;
189 }
190 
191 //===----------------------------------------------------------------------===//
192 // Incorrectly-modelled behavior.
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;
327   clang_analyzer_warnIfReached(); // no-warning
328 }
329 
330 // Invalidate Region even in case of default destructor
331 class InvalidateDestTest {
332 public:
333   int x;
334   int *y;
335   ~InvalidateDestTest();
336 };
337 
test_member_invalidation()338 int test_member_invalidation() {
339 
340   //test invalidation of member variable
341   InvalidateDestTest *test = new InvalidateDestTest();
342   test->x = 5;
343   int *k = &(test->x);
344   clang_analyzer_eval(*k == 5); // expected-warning{{TRUE}}
345   delete test;
346   clang_analyzer_eval(*k == 5); // expected-warning{{UNKNOWN}}
347 
348   //test invalidation of member pointer
349   int localVar = 5;
350   test = new InvalidateDestTest();
351   test->y = &localVar;
352   delete test;
353   clang_analyzer_eval(localVar == 5); // expected-warning{{UNKNOWN}}
354 
355   // Test aray elements are invalidated.
356   int Var1 = 5;
357   int Var2 = 5;
358   InvalidateDestTest *a = new InvalidateDestTest[2];
359   a[0].y = &Var1;
360   a[1].y = &Var2;
361   delete[] a;
362   clang_analyzer_eval(Var1 == 5); // expected-warning{{UNKNOWN}}
363   clang_analyzer_eval(Var2 == 5); // expected-warning{{UNKNOWN}}
364   return 0;
365 }
366