1 //RUN: %clang_analyze_cc1 -analyzer-checker=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 template <typename T>
42 void func_ref(T &a);
43 
44 template <typename T>
45 void func_const_ref(const T &a);
46 
47 template <typename T>
48 void func_value(T a);
49 
50 string my_string = "default";
51 void default_arg(int a = 42, string &b = my_string);
52 
53 } // end namespace std
54 
55 void consume(const char *) {}
56 void consume(const wchar_t *) {}
57 void consume(const char16_t *) {}
58 void consume(const char32_t *) {}
59 
60 //=--------------------------------------=//
61 //     `std::string` member functions     //
62 //=--------------------------------------=//
63 
64 void deref_after_scope_char(bool cond) {
65   const char *c, *d;
66   {
67     std::string s;
68     c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
69     d = s.data();  // expected-note {{Dangling inner pointer obtained here}}
70   }                // expected-note {{Inner pointer invalidated by call to destructor}}
71   // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
72   std::string s;
73   const char *c2 = s.c_str();
74   if (cond) {
75     // expected-note@-1 {{Assuming 'cond' is not equal to 0}}
76     // expected-note@-2 {{Taking true branch}}
77     // expected-note@-3 {{Assuming 'cond' is 0}}
78     // expected-note@-4 {{Taking false branch}}
79     consume(c); // expected-warning {{Use of memory after it is freed}}
80     // expected-note@-1 {{Use of memory after it is freed}}
81   } else {
82     consume(d); // expected-warning {{Use of memory after it is freed}}
83     // expected-note@-1 {{Use of memory after it is freed}}
84   }
85 }
86 
87 void deref_after_scope_char_data_non_const() {
88   char *c;
89   {
90     std::string s;
91     c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
92   }               // expected-note {{Inner pointer invalidated by call to destructor}}
93   std::string s;
94   char *c2 = s.data();
95   consume(c); // expected-warning {{Use of memory after it is freed}}
96   // expected-note@-1 {{Use of memory after it is freed}}
97 }
98 
99 void deref_after_scope_wchar_t(bool cond) {
100   const wchar_t *c, *d;
101   {
102     std::wstring s;
103     c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
104     d = s.data();  // expected-note {{Dangling inner pointer obtained here}}
105   }                // expected-note {{Inner pointer invalidated by call to destructor}}
106   // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
107   std::wstring s;
108   const wchar_t *c2 = s.c_str();
109   if (cond) {
110     // expected-note@-1 {{Assuming 'cond' is not equal to 0}}
111     // expected-note@-2 {{Taking true branch}}
112     // expected-note@-3 {{Assuming 'cond' is 0}}
113     // expected-note@-4 {{Taking false branch}}
114     consume(c); // expected-warning {{Use of memory after it is freed}}
115     // expected-note@-1 {{Use of memory after it is freed}}
116   } else {
117     consume(d); // expected-warning {{Use of memory after it is freed}}
118     // expected-note@-1 {{Use of memory after it is freed}}
119   }
120 }
121 
122 void deref_after_scope_char16_t_cstr() {
123   const char16_t *c16;
124   {
125     std::u16string s16;
126     c16 = s16.c_str(); // expected-note {{Dangling inner pointer obtained here}}
127   }                    // expected-note {{Inner pointer invalidated by call to destructor}}
128   std::u16string s16;
129   const char16_t *c16_2 = s16.c_str();
130   consume(c16); // expected-warning {{Use of memory after it is freed}}
131   // expected-note@-1 {{Use of memory after it is freed}}
132 }
133 
134 void deref_after_scope_char32_t_data() {
135   const char32_t *c32;
136   {
137     std::u32string s32;
138     c32 = s32.data(); // expected-note {{Dangling inner pointer obtained here}}
139   }                   // expected-note {{Inner pointer invalidated by call to destructor}}
140   std::u32string s32;
141   const char32_t *c32_2 = s32.data();
142   consume(c32); // expected-warning {{Use of memory after it is freed}}
143   // expected-note@-1 {{Use of memory after it is freed}}
144 }
145 
146 void multiple_symbols(bool cond) {
147   const char *c1, *d1;
148   {
149     std::string s1;
150     c1 = s1.c_str(); // expected-note {{Dangling inner pointer obtained here}}
151     d1 = s1.data();  // expected-note {{Dangling inner pointer obtained here}}
152     const char *local = s1.c_str();
153     consume(local); // no-warning
154   }                 // expected-note {{Inner pointer invalidated by call to destructor}}
155   // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
156   std::string s2;
157   const char *c2 = s2.c_str();
158   if (cond) {
159     // expected-note@-1 {{Assuming 'cond' is not equal to 0}}
160     // expected-note@-2 {{Taking true branch}}
161     // expected-note@-3 {{Assuming 'cond' is 0}}
162     // expected-note@-4 {{Taking false branch}}
163     consume(c1); // expected-warning {{Use of memory after it is freed}}
164     // expected-note@-1 {{Use of memory after it is freed}}
165   } else {
166     consume(d1); // expected-warning {{Use of memory after it is freed}}
167   }              // expected-note@-1 {{Use of memory after it is freed}}
168 }
169 
170 void deref_after_scope_ok(bool cond) {
171   const char *c, *d;
172   std::string s;
173   {
174     c = s.c_str();
175     d = s.data();
176   }
177   if (cond)
178     consume(c); // no-warning
179   else
180     consume(d); // no-warning
181 }
182 
183 void deref_after_equals() {
184   const char *c;
185   std::string s = "hello";
186   c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
187   s = "world";   // expected-note {{Inner pointer invalidated by call to 'operator='}}
188   consume(c);    // expected-warning {{Use of memory after it is freed}}
189   // expected-note@-1 {{Use of memory after it is freed}}
190 }
191 
192 void deref_after_plus_equals() {
193   const char *c;
194   std::string s = "hello";
195   c = s.data();  // expected-note {{Dangling inner pointer obtained here}}
196   s += " world"; // expected-note {{Inner pointer invalidated by call to 'operator+='}}
197   consume(c);    // expected-warning {{Use of memory after it is freed}}
198   // expected-note@-1 {{Use of memory after it is freed}}
199 }
200 
201 void deref_after_clear() {
202   const char *c;
203   std::string s;
204   c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
205   s.clear();     // expected-note {{Inner pointer invalidated by call to 'clear'}}
206   consume(c);    // expected-warning {{Use of memory after it is freed}}
207   // expected-note@-1 {{Use of memory after it is freed}}
208 }
209 
210 void deref_after_append() {
211   const char *c;
212   std::string s = "hello";
213   c = s.c_str();    // expected-note {{Dangling inner pointer obtained here}}
214   s.append(2, 'x'); // expected-note {{Inner pointer invalidated by call to 'append'}}
215   consume(c);       // expected-warning {{Use of memory after it is freed}}
216   // expected-note@-1 {{Use of memory after it is freed}}
217 }
218 
219 void deref_after_assign() {
220   const char *c;
221   std::string s;
222   c = s.data();     // expected-note {{Dangling inner pointer obtained here}}
223   s.assign(4, 'a'); // expected-note {{Inner pointer invalidated by call to 'assign'}}
224   consume(c);       // expected-warning {{Use of memory after it is freed}}
225   // expected-note@-1 {{Use of memory after it is freed}}
226 }
227 
228 void deref_after_erase() {
229   const char *c;
230   std::string s = "hello";
231   c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
232   s.erase(0, 2); // expected-note {{Inner pointer invalidated by call to 'erase'}}
233   consume(c);    // expected-warning {{Use of memory after it is freed}}
234   // expected-note@-1 {{Use of memory after it is freed}}
235 }
236 
237 void deref_after_insert() {
238   const char *c;
239   std::string s = "ello";
240   c = s.c_str();       // expected-note {{Dangling inner pointer obtained here}}
241   s.insert(0, 1, 'h'); // expected-note {{Inner pointer invalidated by call to 'insert'}}
242   consume(c);          // expected-warning {{Use of memory after it is freed}}
243   // expected-note@-1 {{Use of memory after it is freed}}
244 }
245 
246 void deref_after_replace() {
247   const char *c;
248   std::string s = "hello world";
249   c = s.c_str();             // expected-note {{Dangling inner pointer obtained here}}
250   s.replace(6, 5, "string"); // expected-note {{Inner pointer invalidated by call to 'replace'}}
251   consume(c);                // expected-warning {{Use of memory after it is freed}}
252   // expected-note@-1 {{Use of memory after it is freed}}
253 }
254 
255 void deref_after_pop_back() {
256   const char *c;
257   std::string s;
258   c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
259   s.pop_back();  // expected-note {{Inner pointer invalidated by call to 'pop_back'}}
260   consume(c);    // expected-warning {{Use of memory after it is freed}}
261   // expected-note@-1 {{Use of memory after it is freed}}
262 }
263 
264 void deref_after_push_back() {
265   const char *c;
266   std::string s;
267   c = s.data();     // expected-note {{Dangling inner pointer obtained here}}
268   s.push_back('c'); // expected-note {{Inner pointer invalidated by call to 'push_back'}}
269   consume(c);       // expected-warning {{Use of memory after it is freed}}
270   // expected-note@-1 {{Use of memory after it is freed}}
271 }
272 
273 void deref_after_reserve() {
274   const char *c;
275   std::string s;
276   c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
277   s.reserve(5);  // expected-note {{Inner pointer invalidated by call to 'reserve'}}
278   consume(c);    // expected-warning {{Use of memory after it is freed}}
279   // expected-note@-1 {{Use of memory after it is freed}}
280 }
281 
282 void deref_after_resize() {
283   const char *c;
284   std::string s;
285   c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
286   s.resize(5);  // expected-note {{Inner pointer invalidated by call to 'resize'}}
287   consume(c);   // expected-warning {{Use of memory after it is freed}}
288   // expected-note@-1 {{Use of memory after it is freed}}
289 }
290 
291 void deref_after_shrink_to_fit() {
292   const char *c;
293   std::string s;
294   c = s.data();      // expected-note {{Dangling inner pointer obtained here}}
295   s.shrink_to_fit(); // expected-note {{Inner pointer invalidated by call to 'shrink_to_fit'}}
296   consume(c);        // expected-warning {{Use of memory after it is freed}}
297   // expected-note@-1 {{Use of memory after it is freed}}
298 }
299 
300 void deref_after_swap() {
301   const char *c;
302   std::string s1, s2;
303   c = s1.data(); // expected-note {{Dangling inner pointer obtained here}}
304   s1.swap(s2);   // expected-note {{Inner pointer invalidated by call to 'swap'}}
305   consume(c);    // expected-warning {{Use of memory after it is freed}}
306   // expected-note@-1 {{Use of memory after it is freed}}
307 }
308 
309 //=---------------------------=//
310 //     Other STL functions     //
311 //=---------------------------=//
312 
313 void STL_func_ref() {
314   const char *c;
315   std::string s;
316   c = s.c_str();    // expected-note {{Dangling inner pointer obtained here}}
317   std::func_ref(s); // expected-note {{Inner pointer invalidated by call to 'func_ref'}}
318   consume(c);       // expected-warning {{Use of memory after it is freed}}
319   // expected-note@-1 {{Use of memory after it is freed}}
320 }
321 
322 void STL_func_const_ref() {
323   const char *c;
324   std::string s;
325   c = s.c_str();
326   std::func_const_ref(s);
327   consume(c); // no-warning
328 }
329 
330 void STL_func_value() {
331   const char *c;
332   std::string s;
333   c = s.c_str();
334   std::func_value(s);
335   consume(c); // no-warning
336 }
337 
338 void func_ptr_known() {
339   const char *c;
340   std::string s;
341   void (*func_ptr)(std::string &) = std::func_ref<std::string>;
342   c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
343   func_ptr(s);   // expected-note {{Inner pointer invalidated by call to 'func_ref'}}
344   consume(c);    // expected-warning {{Use of memory after it is freed}}
345   // expected-note@-1 {{Use of memory after it is freed}}
346 }
347 
348 void func_ptr_unknown(void (*func_ptr)(std::string &)) {
349   const char *c;
350   std::string s;
351   c = s.c_str();
352   func_ptr(s);
353   consume(c); // no-warning
354 }
355 
356 void func_default_arg() {
357   const char *c;
358   std::string s;
359   c = s.c_str();     // expected-note {{Dangling inner pointer obtained here}}
360   default_arg(3, s); // expected-note {{Inner pointer invalidated by call to 'default_arg'}}
361   consume(c);        // expected-warning {{Use of memory after it is freed}}
362   // expected-note@-1 {{Use of memory after it is freed}}
363 }
364 
365 struct S {
366   std::string to_string() { return s; }
367 private:
368   std::string s;
369 };
370 
371 const char *escape_via_return_temp() {
372   S x;
373   return x.to_string().c_str(); // expected-note {{Dangling inner pointer obtained here}}
374   // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
375   // expected-warning@-2 {{Use of memory after it is freed}}
376   // expected-note@-3 {{Use of memory after it is freed}}
377 }
378 
379 const char *escape_via_return_local() {
380   std::string s;
381   return s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
382                     // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
383 } // expected-warning {{Use of memory after it is freed}}
384 // expected-note@-1 {{Use of memory after it is freed}}
385 
386 
387 char *c();
388 class A {};
389 
390 void no_CXXRecordDecl() {
391   A a, *b;
392   *(void **)&b = c() + 1;
393   *b = a; // no-crash
394 }
395