1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s 2 // RUN: %clang_cc1 -analyze -analyzer-checker=core,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 testDoubleDelete() { 148 int *p = new int; 149 delete p; 150 delete p; // expected-warning{{Attempt to free released memory}} 151 } 152 153 void testExprDeleteArg() { 154 int i; 155 delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}} 156 } 157 158 void testExprDeleteArrArg() { 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 testAllocDeallocNames() { 164 int *p = new(std::nothrow) int[1]; 165 delete[] (++p); // expected-warning{{Argument to 'delete[]' is offset by 4 bytes from the start of memory allocated by 'new[]'}} 166 } 167 168 //-------------------------------- 169 // Test escape of newed const pointer. Note, a const pointer can be deleted. 170 //-------------------------------- 171 struct StWithConstPtr { 172 const int *memp; 173 }; 174 void escape(const int &x); 175 void escapeStruct(const StWithConstPtr &x); 176 void escapePtr(const StWithConstPtr *x); 177 void escapeVoidPtr(const void *x); 178 179 void testConstEscape() { 180 int *p = new int(1); 181 escape(*p); 182 } // no-warning 183 184 void testConstEscapeStruct() { 185 StWithConstPtr *St = new StWithConstPtr(); 186 escapeStruct(*St); 187 } // no-warning 188 189 void testConstEscapeStructPtr() { 190 StWithConstPtr *St = new StWithConstPtr(); 191 escapePtr(St); 192 } // no-warning 193 194 void testConstEscapeMember() { 195 StWithConstPtr St; 196 St.memp = new int(2); 197 escapeVoidPtr(St.memp); 198 } // no-warning 199 200 void testConstEscapePlacementNew() { 201 int *x = (int *)malloc(sizeof(int)); 202 void *y = new (x) int; 203 escapeVoidPtr(y); 204 } // no-warning 205 206 //============== Test Uninitialized delete delete[]======================== 207 void testUninitDelete() { 208 int *x; 209 int * y = new int; 210 delete y; 211 delete x; // expected-warning{{Argument to 'delete' is uninitialized}} 212 } 213 214 void testUninitDeleteArray() { 215 int *x; 216 int * y = new int[5]; 217 delete[] y; 218 delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}} 219 } 220 221 void testUninitFree() { 222 int *x; 223 free(x); // expected-warning{{Function call argument is an uninitialized value}} 224 } 225 226 void testUninitDeleteSink() { 227 int *x; 228 delete x; // expected-warning{{Argument to 'delete' is uninitialized}} 229 (*(volatile int *)0 = 1); // no warn 230 } 231 232 void testUninitDeleteArraySink() { 233 int *x; 234 delete[] x; // expected-warning{{Argument to 'delete[]' is uninitialized}} 235 (*(volatile int *)0 = 1); // no warn 236 } 237 238 namespace reference_count { 239 class control_block { 240 unsigned count; 241 public: 242 control_block() : count(0) {} 243 void retain() { ++count; } 244 int release() { return --count; } 245 }; 246 247 template <typename T> 248 class shared_ptr { 249 T *p; 250 control_block *control; 251 252 public: 253 shared_ptr() : p(0), control(0) {} 254 explicit shared_ptr(T *p) : p(p), control(new control_block) { 255 control->retain(); 256 } 257 shared_ptr(shared_ptr &other) : p(other.p), control(other.control) { 258 if (control) 259 control->retain(); 260 } 261 ~shared_ptr() { 262 if (control && control->release() == 0) { 263 delete p; 264 delete control; 265 } 266 }; 267 268 T &operator *() { 269 return *p; 270 }; 271 272 void swap(shared_ptr &other) { 273 T *tmp = p; 274 p = other.p; 275 other.p = tmp; 276 277 control_block *ctrlTmp = control; 278 control = other.control; 279 other.control = ctrlTmp; 280 } 281 }; 282 283 void testSingle() { 284 shared_ptr<int> a(new int); 285 *a = 1; 286 } 287 288 void testDouble() { 289 shared_ptr<int> a(new int); 290 shared_ptr<int> b = a; 291 *a = 1; 292 } 293 294 void testInvalidated() { 295 shared_ptr<int> a(new int); 296 shared_ptr<int> b = a; 297 *a = 1; 298 299 extern void use(shared_ptr<int> &); 300 use(b); 301 } 302 303 void testNestedScope() { 304 shared_ptr<int> a(new int); 305 { 306 shared_ptr<int> b = a; 307 } 308 *a = 1; 309 } 310 311 void testSwap() { 312 shared_ptr<int> a(new int); 313 shared_ptr<int> b; 314 shared_ptr<int> c = a; 315 shared_ptr<int>(c).swap(b); 316 } 317 318 void testUseAfterFree() { 319 int *p = new int; 320 { 321 shared_ptr<int> a(p); 322 shared_ptr<int> b = a; 323 } 324 325 // FIXME: We should get a warning here, but we don't because we've 326 // conservatively modeled ~shared_ptr. 327 *p = 1; 328 } 329 } 330 331 // Test double delete 332 class DerefClass{ 333 public: 334 int *x; 335 DerefClass() {} 336 ~DerefClass() {*x = 1;} 337 }; 338 339 void testDoubleDeleteClassInstance() { 340 DerefClass *foo = new DerefClass(); 341 delete foo; 342 delete foo; // expected-warning {{Attempt to delete released memory}} 343 } 344 345 class EmptyClass{ 346 public: 347 EmptyClass() {} 348 ~EmptyClass() {} 349 }; 350 351 void testDoubleDeleteEmptyClass() { 352 EmptyClass *foo = new EmptyClass(); 353 delete foo; 354 delete foo; // expected-warning {{Attempt to delete released memory}} 355 } 356