1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -analyzer-ipa=inlining -cfg-add-implicit-dtors -Wno-null-dereference -verify %s 2 3 void clang_analyzer_eval(bool); 4 5 class A { 6 public: 7 ~A() { 8 int *x = 0; 9 *x = 3; // expected-warning{{Dereference of null pointer}} 10 } 11 }; 12 13 int main() { 14 A a; 15 } 16 17 18 typedef __typeof(sizeof(int)) size_t; 19 void *malloc(size_t); 20 void free(void *); 21 22 class SmartPointer { 23 void *X; 24 public: 25 SmartPointer(void *x) : X(x) {} 26 ~SmartPointer() { 27 free(X); 28 } 29 }; 30 31 void testSmartPointer() { 32 char *mem = (char*)malloc(4); 33 { 34 SmartPointer Deleter(mem); 35 // destructor called here 36 } 37 *mem = 0; // expected-warning{{Use of memory after it is freed}} 38 } 39 40 41 void doSomething(); 42 void testSmartPointer2() { 43 char *mem = (char*)malloc(4); 44 { 45 SmartPointer Deleter(mem); 46 // Remove dead bindings... 47 doSomething(); 48 // destructor called here 49 } 50 *mem = 0; // expected-warning{{Use of memory after it is freed}} 51 } 52 53 54 class Subclass : public SmartPointer { 55 public: 56 Subclass(void *x) : SmartPointer(x) {} 57 }; 58 59 void testSubclassSmartPointer() { 60 char *mem = (char*)malloc(4); 61 { 62 Subclass Deleter(mem); 63 // Remove dead bindings... 64 doSomething(); 65 // destructor called here 66 } 67 *mem = 0; // expected-warning{{Use of memory after it is freed}} 68 } 69 70 71 class MultipleInheritance : public Subclass, public SmartPointer { 72 public: 73 MultipleInheritance(void *a, void *b) : Subclass(a), SmartPointer(b) {} 74 }; 75 76 void testMultipleInheritance1() { 77 char *mem = (char*)malloc(4); 78 { 79 MultipleInheritance Deleter(mem, 0); 80 // Remove dead bindings... 81 doSomething(); 82 // destructor called here 83 } 84 *mem = 0; // expected-warning{{Use of memory after it is freed}} 85 } 86 87 void testMultipleInheritance2() { 88 char *mem = (char*)malloc(4); 89 { 90 MultipleInheritance Deleter(0, mem); 91 // Remove dead bindings... 92 doSomething(); 93 // destructor called here 94 } 95 *mem = 0; // expected-warning{{Use of memory after it is freed}} 96 } 97 98 void testMultipleInheritance3() { 99 char *mem = (char*)malloc(4); 100 { 101 MultipleInheritance Deleter(mem, mem); 102 // Remove dead bindings... 103 doSomething(); 104 // destructor called here 105 // expected-warning@27 {{Attempt to free released memory}} 106 } 107 } 108 109 110 class SmartPointerMember { 111 SmartPointer P; 112 public: 113 SmartPointerMember(void *x) : P(x) {} 114 }; 115 116 void testSmartPointerMember() { 117 char *mem = (char*)malloc(4); 118 { 119 SmartPointerMember Deleter(mem); 120 // Remove dead bindings... 121 doSomething(); 122 // destructor called here 123 } 124 *mem = 0; // expected-warning{{Use of memory after it is freed}} 125 } 126 127 128 struct IntWrapper { 129 IntWrapper() : x(0) {} 130 ~IntWrapper(); 131 int *x; 132 }; 133 134 void testArrayInvalidation() { 135 int i = 42; 136 int j = 42; 137 138 { 139 IntWrapper arr[2]; 140 141 // There should be no undefined value warnings here. 142 // Eventually these should be TRUE as well, but right now 143 // we can't handle array constructors. 144 clang_analyzer_eval(arr[0].x == 0); // expected-warning{{UNKNOWN}} 145 clang_analyzer_eval(arr[1].x == 0); // expected-warning{{UNKNOWN}} 146 147 arr[0].x = &i; 148 arr[1].x = &j; 149 clang_analyzer_eval(*arr[0].x == 42); // expected-warning{{TRUE}} 150 clang_analyzer_eval(*arr[1].x == 42); // expected-warning{{TRUE}} 151 } 152 153 // The destructors should have invalidated i and j. 154 clang_analyzer_eval(i == 42); // expected-warning{{UNKNOWN}} 155 clang_analyzer_eval(j == 42); // expected-warning{{UNKNOWN}} 156 } 157 158 159 160 // Don't crash on a default argument inside an initializer. 161 struct DefaultArg { 162 DefaultArg(int x = 0) {} 163 ~DefaultArg(); 164 }; 165 166 struct InheritsDefaultArg : DefaultArg { 167 InheritsDefaultArg() {} 168 virtual ~InheritsDefaultArg(); 169 }; 170 171 void testDefaultArg() { 172 InheritsDefaultArg a; 173 // Force a bug to be emitted. 174 *(char *)0 = 1; // expected-warning{{Dereference of null pointer}} 175 } 176 177 178 namespace DestructorVirtualCalls { 179 class A { 180 public: 181 int *out1, *out2, *out3; 182 183 virtual int get() { return 1; } 184 185 ~A() { 186 *out1 = get(); 187 } 188 }; 189 190 class B : public A { 191 public: 192 virtual int get() { return 2; } 193 194 ~B() { 195 *out2 = get(); 196 } 197 }; 198 199 class C : public B { 200 public: 201 virtual int get() { return 3; } 202 203 ~C() { 204 *out3 = get(); 205 } 206 }; 207 208 void test() { 209 int a, b, c; 210 211 // New scope for the C object. 212 { 213 C obj; 214 clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}} 215 216 // Sanity check for devirtualization. 217 A *base = &obj; 218 clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}} 219 220 obj.out1 = &a; 221 obj.out2 = &b; 222 obj.out3 = &c; 223 } 224 225 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}} 226 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}} 227 clang_analyzer_eval(c == 3); // expected-warning{{TRUE}} 228 } 229 } 230