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