1 //RUN: %clang_analyze_cc1 -analyzer-checker=alpha.cplusplus.InnerPointer %s -analyzer-output=text -verify 2 3 namespace std { 4 5 typedef int size_type; 6 7 template <typename CharT> 8 class basic_string { 9 public: 10 basic_string(); 11 basic_string(const CharT *s); 12 13 ~basic_string(); 14 void clear(); 15 16 basic_string &operator=(const basic_string &str); 17 basic_string &operator+=(const basic_string &str); 18 19 const CharT *c_str() const; 20 const CharT *data() const; 21 CharT *data(); 22 23 basic_string &append(size_type count, CharT ch); 24 basic_string &assign(size_type count, CharT ch); 25 basic_string &erase(size_type index, size_type count); 26 basic_string &insert(size_type index, size_type count, CharT ch); 27 basic_string &replace(size_type pos, size_type count, const basic_string &str); 28 void pop_back(); 29 void push_back(CharT ch); 30 void reserve(size_type new_cap); 31 void resize(size_type count); 32 void shrink_to_fit(); 33 void swap(basic_string &other); 34 }; 35 36 typedef basic_string<char> string; 37 typedef basic_string<wchar_t> wstring; 38 typedef basic_string<char16_t> u16string; 39 typedef basic_string<char32_t> u32string; 40 41 } // end namespace std 42 43 void consume(const char *) {} 44 void consume(const wchar_t *) {} 45 void consume(const char16_t *) {} 46 void consume(const char32_t *) {} 47 48 void deref_after_scope_char(bool cond) { 49 const char *c, *d; 50 { 51 std::string s; 52 c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} 53 d = s.data(); // expected-note {{Dangling inner pointer obtained here}} 54 } // expected-note {{Inner pointer invalidated by call to destructor}} 55 // expected-note@-1 {{Inner pointer invalidated by call to destructor}} 56 std::string s; 57 const char *c2 = s.c_str(); 58 if (cond) { 59 // expected-note@-1 {{Assuming 'cond' is not equal to 0}} 60 // expected-note@-2 {{Taking true branch}} 61 // expected-note@-3 {{Assuming 'cond' is 0}} 62 // expected-note@-4 {{Taking false branch}} 63 consume(c); // expected-warning {{Use of memory after it is freed}} 64 // expected-note@-1 {{Use of memory after it is freed}} 65 } else { 66 consume(d); // expected-warning {{Use of memory after it is freed}} 67 // expected-note@-1 {{Use of memory after it is freed}} 68 } 69 } 70 71 void deref_after_scope_char_data_non_const() { 72 char *c; 73 { 74 std::string s; 75 c = s.data(); // expected-note {{Dangling inner pointer obtained here}} 76 } // expected-note {{Inner pointer invalidated by call to destructor}} 77 std::string s; 78 char *c2 = s.data(); 79 consume(c); // expected-warning {{Use of memory after it is freed}} 80 // expected-note@-1 {{Use of memory after it is freed}} 81 } 82 83 void deref_after_scope_wchar_t(bool cond) { 84 const wchar_t *c, *d; 85 { 86 std::wstring s; 87 c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} 88 d = s.data(); // expected-note {{Dangling inner pointer obtained here}} 89 } // expected-note {{Inner pointer invalidated by call to destructor}} 90 // expected-note@-1 {{Inner pointer invalidated by call to destructor}} 91 std::wstring s; 92 const wchar_t *c2 = s.c_str(); 93 if (cond) { 94 // expected-note@-1 {{Assuming 'cond' is not equal to 0}} 95 // expected-note@-2 {{Taking true branch}} 96 // expected-note@-3 {{Assuming 'cond' is 0}} 97 // expected-note@-4 {{Taking false branch}} 98 consume(c); // expected-warning {{Use of memory after it is freed}} 99 // expected-note@-1 {{Use of memory after it is freed}} 100 } else { 101 consume(d); // expected-warning {{Use of memory after it is freed}} 102 // expected-note@-1 {{Use of memory after it is freed}} 103 } 104 } 105 106 void deref_after_scope_char16_t_cstr() { 107 const char16_t *c16; 108 { 109 std::u16string s16; 110 c16 = s16.c_str(); // expected-note {{Dangling inner pointer obtained here}} 111 } // expected-note {{Inner pointer invalidated by call to destructor}} 112 std::u16string s16; 113 const char16_t *c16_2 = s16.c_str(); 114 consume(c16); // expected-warning {{Use of memory after it is freed}} 115 // expected-note@-1 {{Use of memory after it is freed}} 116 } 117 118 void deref_after_scope_char32_t_data() { 119 const char32_t *c32; 120 { 121 std::u32string s32; 122 c32 = s32.data(); // expected-note {{Dangling inner pointer obtained here}} 123 } // expected-note {{Inner pointer invalidated by call to destructor}} 124 std::u32string s32; 125 const char32_t *c32_2 = s32.data(); 126 consume(c32); // expected-warning {{Use of memory after it is freed}} 127 // expected-note@-1 {{Use of memory after it is freed}} 128 } 129 130 void multiple_symbols(bool cond) { 131 const char *c1, *d1; 132 { 133 std::string s1; 134 c1 = s1.c_str(); // expected-note {{Dangling inner pointer obtained here}} 135 d1 = s1.data(); // expected-note {{Dangling inner pointer obtained here}} 136 const char *local = s1.c_str(); 137 consume(local); // no-warning 138 } // expected-note {{Inner pointer invalidated by call to destructor}} 139 // expected-note@-1 {{Inner pointer invalidated by call to destructor}} 140 std::string s2; 141 const char *c2 = s2.c_str(); 142 if (cond) { 143 // expected-note@-1 {{Assuming 'cond' is not equal to 0}} 144 // expected-note@-2 {{Taking true branch}} 145 // expected-note@-3 {{Assuming 'cond' is 0}} 146 // expected-note@-4 {{Taking false branch}} 147 consume(c1); // expected-warning {{Use of memory after it is freed}} 148 // expected-note@-1 {{Use of memory after it is freed}} 149 } else { 150 consume(d1); // expected-warning {{Use of memory after it is freed}} 151 } // expected-note@-1 {{Use of memory after it is freed}} 152 } 153 154 void deref_after_equals() { 155 const char *c; 156 std::string s = "hello"; 157 c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} 158 s = "world"; // expected-note {{Inner pointer invalidated by call to 'operator='}} 159 consume(c); // expected-warning {{Use of memory after it is freed}} 160 // expected-note@-1 {{Use of memory after it is freed}} 161 } 162 163 void deref_after_plus_equals() { 164 const char *c; 165 std::string s = "hello"; 166 c = s.data(); // expected-note {{Dangling inner pointer obtained here}} 167 s += " world"; // expected-note {{Inner pointer invalidated by call to 'operator+='}} 168 consume(c); // expected-warning {{Use of memory after it is freed}} 169 // expected-note@-1 {{Use of memory after it is freed}} 170 } 171 172 void deref_after_clear() { 173 const char *c; 174 std::string s; 175 c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} 176 s.clear(); // expected-note {{Inner pointer invalidated by call to 'clear'}} 177 consume(c); // expected-warning {{Use of memory after it is freed}} 178 // expected-note@-1 {{Use of memory after it is freed}} 179 } 180 181 void deref_after_append() { 182 const char *c; 183 std::string s = "hello"; 184 c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} 185 s.append(2, 'x'); // expected-note {{Inner pointer invalidated by call to 'append'}} 186 consume(c); // expected-warning {{Use of memory after it is freed}} 187 // expected-note@-1 {{Use of memory after it is freed}} 188 } 189 190 void deref_after_assign() { 191 const char *c; 192 std::string s; 193 c = s.data(); // expected-note {{Dangling inner pointer obtained here}} 194 s.assign(4, 'a'); // expected-note {{Inner pointer invalidated by call to 'assign'}} 195 consume(c); // expected-warning {{Use of memory after it is freed}} 196 // expected-note@-1 {{Use of memory after it is freed}} 197 } 198 199 void deref_after_erase() { 200 const char *c; 201 std::string s = "hello"; 202 c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} 203 s.erase(0, 2); // expected-note {{Inner pointer invalidated by call to 'erase'}} 204 consume(c); // expected-warning {{Use of memory after it is freed}} 205 // expected-note@-1 {{Use of memory after it is freed}} 206 } 207 208 void deref_after_insert() { 209 const char *c; 210 std::string s = "ello"; 211 c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} 212 s.insert(0, 1, 'h'); // expected-note {{Inner pointer invalidated by call to 'insert'}} 213 consume(c); // expected-warning {{Use of memory after it is freed}} 214 // expected-note@-1 {{Use of memory after it is freed}} 215 } 216 217 void deref_after_replace() { 218 const char *c; 219 std::string s = "hello world"; 220 c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} 221 s.replace(6, 5, "string"); // expected-note {{Inner pointer invalidated by call to 'replace'}} 222 consume(c); // expected-warning {{Use of memory after it is freed}} 223 // expected-note@-1 {{Use of memory after it is freed}} 224 } 225 226 void deref_after_pop_back() { 227 const char *c; 228 std::string s; 229 c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} 230 s.pop_back(); // expected-note {{Inner pointer invalidated by call to 'pop_back'}} 231 consume(c); // expected-warning {{Use of memory after it is freed}} 232 // expected-note@-1 {{Use of memory after it is freed}} 233 } 234 235 void deref_after_push_back() { 236 const char *c; 237 std::string s; 238 c = s.data(); // expected-note {{Dangling inner pointer obtained here}} 239 s.push_back('c'); // expected-note {{Inner pointer invalidated by call to 'push_back'}} 240 consume(c); // expected-warning {{Use of memory after it is freed}} 241 // expected-note@-1 {{Use of memory after it is freed}} 242 } 243 244 void deref_after_reserve() { 245 const char *c; 246 std::string s; 247 c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} 248 s.reserve(5); // expected-note {{Inner pointer invalidated by call to 'reserve'}} 249 consume(c); // expected-warning {{Use of memory after it is freed}} 250 // expected-note@-1 {{Use of memory after it is freed}} 251 } 252 253 void deref_after_resize() { 254 const char *c; 255 std::string s; 256 c = s.data(); // expected-note {{Dangling inner pointer obtained here}} 257 s.resize(5); // expected-note {{Inner pointer invalidated by call to 'resize'}} 258 consume(c); // expected-warning {{Use of memory after it is freed}} 259 // expected-note@-1 {{Use of memory after it is freed}} 260 } 261 262 void deref_after_shrink_to_fit() { 263 const char *c; 264 std::string s; 265 c = s.data(); // expected-note {{Dangling inner pointer obtained here}} 266 s.shrink_to_fit(); // expected-note {{Inner pointer invalidated by call to 'shrink_to_fit'}} 267 consume(c); // expected-warning {{Use of memory after it is freed}} 268 // expected-note@-1 {{Use of memory after it is freed}} 269 } 270 271 void deref_after_swap() { 272 const char *c; 273 std::string s1, s2; 274 c = s1.data(); // expected-note {{Dangling inner pointer obtained here}} 275 s1.swap(s2); // expected-note {{Inner pointer invalidated by call to 'swap'}} 276 consume(c); // expected-warning {{Use of memory after it is freed}} 277 // expected-note@-1 {{Use of memory after it is freed}} 278 } 279 280 void deref_after_scope_ok(bool cond) { 281 const char *c, *d; 282 std::string s; 283 { 284 c = s.c_str(); 285 d = s.data(); 286 } 287 if (cond) 288 consume(c); // no-warning 289 else 290 consume(d); // no-warning 291 } 292