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