1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s 2 // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s 3 // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -verify %s 4 // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -verify %s 5 // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s 6 // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s 7 // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -DTEST_INLINABLE_ALLOCATORS -verify %s 8 // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -DTEST_INLINABLE_ALLOCATORS -verify %s 9 10 #include "Inputs/system-header-simulator-cxx.h" 11 12 typedef __typeof__(sizeof(int)) size_t; 13 extern "C" void *malloc(size_t); 14 extern "C" void free (void* ptr); 15 int *global; 16 17 //------------------ 18 // check for leaks 19 //------------------ 20 21 //----- Standard non-placement operators 22 void testGlobalOpNew() { 23 void *p = operator new(0); 24 } 25 #ifdef LEAKS 26 // expected-warning@-2{{Potential leak of memory pointed to by 'p'}} 27 #endif 28 29 void testGlobalOpNewArray() { 30 void *p = operator new[](0); 31 } 32 #ifdef LEAKS 33 // expected-warning@-2{{Potential leak of memory pointed to by 'p'}} 34 #endif 35 36 void testGlobalNewExpr() { 37 int *p = new int; 38 } 39 #ifdef LEAKS 40 // expected-warning@-2{{Potential leak of memory pointed to by 'p'}} 41 #endif 42 43 void testGlobalNewExprArray() { 44 int *p = new int[0]; 45 } 46 #ifdef LEAKS 47 // expected-warning@-2{{Potential leak of memory pointed to by 'p'}} 48 #endif 49 50 //----- Standard nothrow placement operators 51 void testGlobalNoThrowPlacementOpNewBeforeOverload() { 52 void *p = operator new(0, std::nothrow); 53 } 54 #ifdef LEAKS 55 #ifndef TEST_INLINABLE_ALLOCATORS 56 // expected-warning@-3{{Potential leak of memory pointed to by 'p'}} 57 #endif 58 #endif 59 60 void testGlobalNoThrowPlacementExprNewBeforeOverload() { 61 int *p = new(std::nothrow) int; 62 } 63 #ifdef LEAKS 64 #ifndef TEST_INLINABLE_ALLOCATORS 65 // expected-warning@-3{{Potential leak of memory pointed to by 'p'}} 66 #endif 67 #endif 68 69 //----- Standard pointer placement operators 70 void testGlobalPointerPlacementNew() { 71 int i; 72 73 void *p1 = operator new(0, &i); // no warn 74 75 void *p2 = operator new[](0, &i); // no warn 76 77 int *p3 = new(&i) int; // no warn 78 79 int *p4 = new(&i) int[0]; // no warn 80 } 81 82 //----- Other cases 83 void testNewMemoryIsInHeap() { 84 int *p = new int; 85 if (global != p) // condition is always true as 'p' wraps a heap region that 86 // is different from a region wrapped by 'global' 87 global = p; // pointer escapes 88 } 89 90 struct PtrWrapper { 91 int *x; 92 93 PtrWrapper(int *input) : x(input) {} 94 }; 95 96 void testNewInvalidationPlacement(PtrWrapper *w) { 97 // Ensure that we don't consider this a leak. 98 new (w) PtrWrapper(new int); // no warn 99 } 100 101 //----------------------------------------- 102 // check for usage of zero-allocated memory 103 //----------------------------------------- 104 105 void testUseZeroAlloc1() { 106 int *p = (int *)operator new(0); 107 *p = 1; // expected-warning {{Use of zero-allocated memory}} 108 delete p; 109 } 110 111 int testUseZeroAlloc2() { 112 int *p = (int *)operator new[](0); 113 return p[0]; // expected-warning {{Use of zero-allocated memory}} 114 delete[] p; 115 } 116 117 void f(int); 118 119 void testUseZeroAlloc3() { 120 int *p = new int[0]; 121 f(*p); // expected-warning {{Use of zero-allocated memory}} 122 delete[] p; 123 } 124 125 //--------------- 126 // other checks 127 //--------------- 128 129 class SomeClass { 130 public: 131 void f(int *p); 132 }; 133 134 void f(int *p1, int *p2 = 0, int *p3 = 0); 135 void g(SomeClass &c, ...); 136 137 void testUseFirstArgAfterDelete() { 138 int *p = new int; 139 delete p; 140 f(p); // expected-warning{{Use of memory after it is freed}} 141 } 142 143 void testUseMiddleArgAfterDelete(int *p) { 144 delete p; 145 f(0, p); // expected-warning{{Use of memory after it is freed}} 146 } 147 148 void testUseLastArgAfterDelete(int *p) { 149 delete p; 150 f(0, 0, p); // expected-warning{{Use of memory after it is freed}} 151 } 152 153 void testUseSeveralArgsAfterDelete(int *p) { 154 delete p; 155 f(p, p, p); // expected-warning{{Use of memory after it is freed}} 156 } 157 158 void testUseRefArgAfterDelete(SomeClass &c) { 159 delete &c; 160 g(c); // expected-warning{{Use of memory after it is freed}} 161 } 162 163 void testVariadicArgAfterDelete() { 164 SomeClass c; 165 int *p = new int; 166 delete p; 167 g(c, 0, p); // expected-warning{{Use of memory after it is freed}} 168 } 169 170 void testUseMethodArgAfterDelete(int *p) { 171 SomeClass *c = new SomeClass; 172 delete p; 173 c->f(p); // expected-warning{{Use of memory after it is freed}} 174 } 175 176 void testUseThisAfterDelete() { 177 SomeClass *c = new SomeClass; 178 delete c; 179 c->f(0); // expected-warning{{Use of memory after it is freed}} 180 } 181 182 void testDoubleDelete() { 183 int *p = new int; 184 delete p; 185 delete p; // expected-warning{{Attempt to free released memory}} 186 } 187 188 void testExprDeleteArg() { 189 int i; 190 delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}} 191 } 192 193 void testExprDeleteArrArg() { 194 int i; 195 delete[] &i; // expected-warning{{Argument to 'delete[]' is the address of the local variable 'i', which is not memory allocated by 'new[]'}} 196 } 197 198 void testAllocDeallocNames() { 199 int *p = new(std::nothrow) int[1]; 200 delete[] (++p); 201 #ifndef TEST_INLINABLE_ALLOCATORS 202 // expected-warning@-2{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}} 203 #endif 204 } 205 206 //-------------------------------- 207 // Test escape of newed const pointer. Note, a const pointer can be deleted. 208 //-------------------------------- 209 struct StWithConstPtr { 210 const int *memp; 211 }; 212 void escape(const int &x); 213 void escapeStruct(const StWithConstPtr &x); 214 void escapePtr(const StWithConstPtr *x); 215 void escapeVoidPtr(const void *x); 216 217 void testConstEscape() { 218 int *p = new int(1); 219 escape(*p); 220 } // no-warning 221 222 void testConstEscapeStruct() { 223 StWithConstPtr *St = new StWithConstPtr(); 224 escapeStruct(*St); 225 } // no-warning 226 227 void testConstEscapeStructPtr() { 228 StWithConstPtr *St = new StWithConstPtr(); 229 escapePtr(St); 230 } // no-warning 231 232 void testConstEscapeMember() { 233 StWithConstPtr St; 234 St.memp = new int(2); 235 escapeVoidPtr(St.memp); 236 } // no-warning 237 238 void testConstEscapePlacementNew() { 239 int *x = (int *)malloc(sizeof(int)); 240 void *y = new (x) int; 241 escapeVoidPtr(y); 242 } // no-warning 243 244 //============== Test Uninitialized delete delete[]======================== 245 void testUninitDelete() { 246 int *x; 247 int * y = new int; 248 delete y; 249 delete x; // expected-warning{{Argument to 'delete' is uninitialized}} 250 } 251 252 void testUninitDeleteArray() { 253 int *x; 254 int * y = new int[5]; 255 delete[] y; 256 delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}} 257 } 258 259 void testUninitFree() { 260 int *x; 261 free(x); // expected-warning{{1st function call argument is an uninitialized value}} 262 } 263 264 void testUninitDeleteSink() { 265 int *x; 266 delete x; // expected-warning{{Argument to 'delete' is uninitialized}} 267 (*(volatile int *)0 = 1); // no warn 268 } 269 270 void testUninitDeleteArraySink() { 271 int *x; 272 delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}} 273 (*(volatile int *)0 = 1); // no warn 274 } 275 276 namespace reference_count { 277 class control_block { 278 unsigned count; 279 public: 280 control_block() : count(0) {} 281 void retain() { ++count; } 282 int release() { return --count; } 283 }; 284 285 template <typename T> 286 class shared_ptr { 287 T *p; 288 control_block *control; 289 290 public: 291 shared_ptr() : p(0), control(0) {} 292 explicit shared_ptr(T *p) : p(p), control(new control_block) { 293 control->retain(); 294 } 295 shared_ptr(shared_ptr &other) : p(other.p), control(other.control) { 296 if (control) 297 control->retain(); 298 } 299 ~shared_ptr() { 300 if (control && control->release() == 0) { 301 delete p; 302 delete control; 303 } 304 }; 305 306 T &operator *() { 307 return *p; 308 }; 309 310 void swap(shared_ptr &other) { 311 T *tmp = p; 312 p = other.p; 313 other.p = tmp; 314 315 control_block *ctrlTmp = control; 316 control = other.control; 317 other.control = ctrlTmp; 318 } 319 }; 320 321 void testSingle() { 322 shared_ptr<int> a(new int); 323 *a = 1; 324 } 325 326 void testDouble() { 327 shared_ptr<int> a(new int); 328 shared_ptr<int> b = a; 329 *a = 1; 330 } 331 332 void testInvalidated() { 333 shared_ptr<int> a(new int); 334 shared_ptr<int> b = a; 335 *a = 1; 336 337 extern void use(shared_ptr<int> &); 338 use(b); 339 } 340 341 void testNestedScope() { 342 shared_ptr<int> a(new int); 343 { 344 shared_ptr<int> b = a; 345 } 346 *a = 1; 347 } 348 349 void testSwap() { 350 shared_ptr<int> a(new int); 351 shared_ptr<int> b; 352 shared_ptr<int> c = a; 353 shared_ptr<int>(c).swap(b); 354 } 355 356 void testUseAfterFree() { 357 int *p = new int; 358 { 359 shared_ptr<int> a(p); 360 shared_ptr<int> b = a; 361 } 362 363 // FIXME: We should get a warning here, but we don't because we've 364 // conservatively modeled ~shared_ptr. 365 *p = 1; 366 } 367 } 368 369 // Test double delete 370 class DerefClass{ 371 public: 372 int *x; 373 DerefClass() {} 374 ~DerefClass() {*x = 1;} 375 }; 376 377 void testDoubleDeleteClassInstance() { 378 DerefClass *foo = new DerefClass(); 379 delete foo; 380 delete foo; // expected-warning {{Attempt to delete released memory}} 381 } 382 383 class EmptyClass{ 384 public: 385 EmptyClass() {} 386 ~EmptyClass() {} 387 }; 388 389 void testDoubleDeleteEmptyClass() { 390 EmptyClass *foo = new EmptyClass(); 391 delete foo; 392 delete foo; // expected-warning {{Attempt to delete released memory}} 393 } 394 395 struct Base { 396 virtual ~Base() {} 397 }; 398 399 struct Derived : Base { 400 }; 401 402 Base *allocate() { 403 return new Derived; 404 } 405 406 void shouldNotReportLeak() { 407 Derived *p = (Derived *)allocate(); 408 delete p; 409 } 410