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