1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -verify %s 2 #include "Inputs/system-header-simulator-cxx.h" 3 4 void clang_analyzer_eval(bool); 5 6 typedef __typeof__(sizeof(int)) size_t; 7 extern "C" void *malloc(size_t); 8 extern "C" void free(void *); 9 10 int someGlobal; 11 12 class SomeClass { 13 public: 14 void f(int *p); 15 }; 16 17 void testImplicitlyDeclaredGlobalNew() { 18 if (someGlobal != 0) 19 return; 20 21 // This used to crash because the global operator new is being implicitly 22 // declared and it does not have a valid source location. (PR13090) 23 void *x = ::operator new(0); 24 ::operator delete(x); 25 26 // Check that the new/delete did not invalidate someGlobal; 27 clang_analyzer_eval(someGlobal == 0); // expected-warning{{TRUE}} 28 } 29 30 void *testPlacementNew() { 31 int *x = (int *)malloc(sizeof(int)); 32 *x = 1; 33 clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}}; 34 35 void *y = new (x) int; 36 clang_analyzer_eval(x == y); // expected-warning{{TRUE}}; 37 clang_analyzer_eval(*x == 1); // expected-warning{{UNKNOWN}}; 38 39 return y; 40 } 41 42 void *operator new(size_t, size_t, int *); 43 void *testCustomNew() { 44 int x[1] = {1}; 45 clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}}; 46 47 void *y = new (0, x) int; 48 clang_analyzer_eval(*x == 1); // expected-warning{{UNKNOWN}}; 49 50 return y; // no-warning 51 } 52 53 void *operator new(size_t, void *, void *); 54 void *testCustomNewMalloc() { 55 int *x = (int *)malloc(sizeof(int)); 56 57 // Should be no-warning (the custom allocator could have freed x). 58 void *y = new (0, x) int; // no-warning 59 60 return y; 61 } 62 63 void testScalarInitialization() { 64 int *n = new int(3); 65 clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}} 66 67 new (n) int(); 68 clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}} 69 70 new (n) int{3}; 71 clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}} 72 73 new (n) int{}; 74 clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}} 75 } 76 77 struct PtrWrapper { 78 int *x; 79 80 PtrWrapper(int *input) : x(input) {} 81 }; 82 83 PtrWrapper *testNewInvalidation() { 84 // Ensure that we don't consider this a leak. 85 return new PtrWrapper(static_cast<int *>(malloc(4))); // no-warning 86 } 87 88 void testNewInvalidationPlacement(PtrWrapper *w) { 89 // Ensure that we don't consider this a leak. 90 new (w) PtrWrapper(static_cast<int *>(malloc(4))); // no-warning 91 } 92 93 int **testNewInvalidationScalar() { 94 // Ensure that we don't consider this a leak. 95 return new (int *)(static_cast<int *>(malloc(4))); // no-warning 96 } 97 98 void testNewInvalidationScalarPlacement(int **p) { 99 // Ensure that we don't consider this a leak. 100 new (p) (int *)(static_cast<int *>(malloc(4))); // no-warning 101 } 102 103 void testCacheOut(PtrWrapper w) { 104 extern bool coin(); 105 if (coin()) 106 w.x = 0; 107 new (&w.x) (int*)(0); // we cache out here; don't crash 108 } 109 110 void testUseAfter(int *p) { 111 SomeClass *c = new SomeClass; 112 free(p); 113 c->f(p); // expected-warning{{Use of memory after it is freed}} 114 delete c; 115 } 116 117 //-------------------------------------------------------------------- 118 // Check for intersection with other checkers from MallocChecker.cpp 119 // bounded with unix.Malloc 120 //-------------------------------------------------------------------- 121 122 // new/delete oparators are subjects of cplusplus.NewDelete. 123 void testNewDeleteNoWarn() { 124 int i; 125 delete &i; // no-warning 126 127 int *p1 = new int; 128 delete ++p1; // no-warning 129 130 int *p2 = new int; 131 delete p2; 132 delete p2; // no-warning 133 134 int *p3 = new int; // no-warning 135 } 136 137 // unix.Malloc does not know about operators new/delete. 138 void testDeleteMallocked() { 139 int *x = (int *)malloc(sizeof(int)); 140 delete x; // FIXME: Shoud detect pointer escape and keep silent after 'delete' is modeled properly. 141 } // expected-warning{{Potential leak of memory pointed to by 'x'}} 142 143 void testDeleteOpAfterFree() { 144 int *p = (int *)malloc(sizeof(int)); 145 free(p); 146 operator delete(p); // expected-warning{{Use of memory after it is freed}} 147 } 148 149 void testDeleteAfterFree() { 150 int *p = (int *)malloc(sizeof(int)); 151 free(p); 152 delete p; // expected-warning{{Use of memory after it is freed}} 153 } 154 155 void testStandardPlacementNewAfterFree() { 156 int *p = (int *)malloc(sizeof(int)); 157 free(p); 158 p = new(p) int; // expected-warning{{Use of memory after it is freed}} 159 } 160 161 void testCustomPlacementNewAfterFree() { 162 int *p = (int *)malloc(sizeof(int)); 163 free(p); 164 p = new(0, p) int; // expected-warning{{Use of memory after it is freed}} 165 } 166 167 void testUsingThisAfterDelete() { 168 SomeClass *c = new SomeClass; 169 delete c; 170 c->f(0); // no-warning 171 } 172 173 //-------------------------------- 174 // Incorrectly-modelled behavior 175 //-------------------------------- 176 177 int testNoInitialization() { 178 int *n = new int; 179 180 // Should warn that *n is uninitialized. 181 if (*n) { // no-warning 182 delete n; 183 return 0; 184 } 185 delete n; 186 return 1; 187 } 188 189 int testNoInitializationPlacement() { 190 int n; 191 new (&n) int; 192 193 // Should warn that n is uninitialized. 194 if (n) { // no-warning 195 return 0; 196 } 197 return 1; 198 } 199