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 4void clang_analyzer_eval(bool); 5 6typedef __typeof__(sizeof(int)) size_t; 7extern "C" void *malloc(size_t); 8extern "C" void free(void *); 9 10int someGlobal; 11 12class SomeClass { 13public: 14 void f(int *p); 15}; 16 17void 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 30void *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 51} 52 53void *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 63void 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 77struct 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. 85 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 101} 102 103void 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 110void 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. 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. 141} // expected-warning{{Potential leak of memory pointed to by 'x'}} 142 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} 166 167void testUsingThisAfterDelete() { 168 SomeClass *c = new SomeClass; 169 delete c; 170 c->f(0); // no-warning 171} 172 173void 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 187int 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 199int 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 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 270//Deleting a non-class pointer should not crash/warn 271void 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} 354