diff options
Diffstat (limited to 'test/Analysis/inner-pointer.cpp')
-rw-r--r-- | test/Analysis/inner-pointer.cpp | 316 |
1 files changed, 175 insertions, 141 deletions
diff --git a/test/Analysis/inner-pointer.cpp b/test/Analysis/inner-pointer.cpp index 230e3396c59ea..81b750d7e5dd3 100644 --- a/test/Analysis/inner-pointer.cpp +++ b/test/Analysis/inner-pointer.cpp @@ -1,43 +1,9 @@ -//RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.InnerPointer %s -analyzer-output=text -verify +// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.InnerPointer \ +// RUN: %s -analyzer-output=text -verify +#include "Inputs/system-header-simulator-cxx.h" namespace std { -typedef int size_type; - -template <typename CharT> -class basic_string { -public: - basic_string(); - basic_string(const CharT *s); - - ~basic_string(); - void clear(); - - basic_string &operator=(const basic_string &str); - basic_string &operator+=(const basic_string &str); - - const CharT *c_str() const; - const CharT *data() const; - CharT *data(); - - basic_string &append(size_type count, CharT ch); - basic_string &assign(size_type count, CharT ch); - basic_string &erase(size_type index, size_type count); - basic_string &insert(size_type index, size_type count, CharT ch); - basic_string &replace(size_type pos, size_type count, const basic_string &str); - void pop_back(); - void push_back(CharT ch); - void reserve(size_type new_cap); - void resize(size_type count); - void shrink_to_fit(); - void swap(basic_string &other); -}; - -typedef basic_string<char> string; -typedef basic_string<wchar_t> wstring; -typedef basic_string<char16_t> u16string; -typedef basic_string<char32_t> u32string; - template <typename T> void func_ref(T &a); @@ -65,10 +31,10 @@ void deref_after_scope_char(bool cond) { const char *c, *d; { std::string s; - c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} - d = s.data(); // expected-note {{Dangling inner pointer obtained here}} - } // expected-note {{Inner pointer invalidated by call to destructor}} - // expected-note@-1 {{Inner pointer invalidated by call to destructor}} + c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + d = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + } // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}} + // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}} std::string s; const char *c2 = s.c_str(); if (cond) { @@ -76,11 +42,11 @@ void deref_after_scope_char(bool cond) { // expected-note@-2 {{Taking true branch}} // expected-note@-3 {{Assuming 'cond' is 0}} // expected-note@-4 {{Taking false branch}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } else { - consume(d); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + consume(d); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } } @@ -88,22 +54,22 @@ void deref_after_scope_char_data_non_const() { char *c; { std::string s; - c = s.data(); // expected-note {{Dangling inner pointer obtained here}} - } // expected-note {{Inner pointer invalidated by call to destructor}} + c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + } // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}} std::string s; char *c2 = s.data(); - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_scope_wchar_t(bool cond) { const wchar_t *c, *d; { std::wstring s; - c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} - d = s.data(); // expected-note {{Dangling inner pointer obtained here}} - } // expected-note {{Inner pointer invalidated by call to destructor}} - // expected-note@-1 {{Inner pointer invalidated by call to destructor}} + c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::wstring' obtained here}} + d = s.data(); // expected-note {{Pointer to inner buffer of 'std::wstring' obtained here}} + } // expected-note {{Inner buffer of 'std::wstring' deallocated by call to destructor}} + // expected-note@-1 {{Inner buffer of 'std::wstring' deallocated by call to destructor}} std::wstring s; const wchar_t *c2 = s.c_str(); if (cond) { @@ -111,11 +77,11 @@ void deref_after_scope_wchar_t(bool cond) { // expected-note@-2 {{Taking true branch}} // expected-note@-3 {{Assuming 'cond' is 0}} // expected-note@-4 {{Taking false branch}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } else { - consume(d); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + consume(d); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } } @@ -123,36 +89,36 @@ void deref_after_scope_char16_t_cstr() { const char16_t *c16; { std::u16string s16; - c16 = s16.c_str(); // expected-note {{Dangling inner pointer obtained here}} - } // expected-note {{Inner pointer invalidated by call to destructor}} + c16 = s16.c_str(); // expected-note {{Pointer to inner buffer of 'std::u16string' obtained here}} + } // expected-note {{Inner buffer of 'std::u16string' deallocated by call to destructor}} std::u16string s16; const char16_t *c16_2 = s16.c_str(); - consume(c16); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + consume(c16); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_scope_char32_t_data() { const char32_t *c32; { std::u32string s32; - c32 = s32.data(); // expected-note {{Dangling inner pointer obtained here}} - } // expected-note {{Inner pointer invalidated by call to destructor}} + c32 = s32.data(); // expected-note {{Pointer to inner buffer of 'std::u32string' obtained here}} + } // expected-note {{Inner buffer of 'std::u32string' deallocated by call to destructor}} std::u32string s32; const char32_t *c32_2 = s32.data(); - consume(c32); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + consume(c32); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void multiple_symbols(bool cond) { const char *c1, *d1; { std::string s1; - c1 = s1.c_str(); // expected-note {{Dangling inner pointer obtained here}} - d1 = s1.data(); // expected-note {{Dangling inner pointer obtained here}} + c1 = s1.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + d1 = s1.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} const char *local = s1.c_str(); consume(local); // no-warning - } // expected-note {{Inner pointer invalidated by call to destructor}} - // expected-note@-1 {{Inner pointer invalidated by call to destructor}} + } // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}} + // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}} std::string s2; const char *c2 = s2.c_str(); if (cond) { @@ -160,11 +126,11 @@ void multiple_symbols(bool cond) { // expected-note@-2 {{Taking true branch}} // expected-note@-3 {{Assuming 'cond' is 0}} // expected-note@-4 {{Taking false branch}} - consume(c1); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + consume(c1); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } else { - consume(d1); // expected-warning {{Use of memory after it is freed}} - } // expected-note@-1 {{Use of memory after it is freed}} + consume(d1); // expected-warning {{Inner pointer of container used after re/deallocation}} + } // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_scope_ok(bool cond) { @@ -183,127 +149,159 @@ void deref_after_scope_ok(bool cond) { void deref_after_equals() { const char *c; std::string s = "hello"; - c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} - s = "world"; // expected-note {{Inner pointer invalidated by call to 'operator='}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s = "world"; // expected-note {{Inner buffer of 'std::string' reallocated by call to 'operator='}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_plus_equals() { const char *c; std::string s = "hello"; - c = s.data(); // expected-note {{Dangling inner pointer obtained here}} - s += " world"; // expected-note {{Inner pointer invalidated by call to 'operator+='}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s += " world"; // expected-note {{Inner buffer of 'std::string' reallocated by call to 'operator+='}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_clear() { const char *c; std::string s; - c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} - s.clear(); // expected-note {{Inner pointer invalidated by call to 'clear'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s.clear(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'clear'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_append() { const char *c; std::string s = "hello"; - c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} - s.append(2, 'x'); // expected-note {{Inner pointer invalidated by call to 'append'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s.append(2, 'x'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'append'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_assign() { const char *c; std::string s; - c = s.data(); // expected-note {{Dangling inner pointer obtained here}} - s.assign(4, 'a'); // expected-note {{Inner pointer invalidated by call to 'assign'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s.assign(4, 'a'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'assign'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_erase() { const char *c; std::string s = "hello"; - c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} - s.erase(0, 2); // expected-note {{Inner pointer invalidated by call to 'erase'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s.erase(0, 2); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'erase'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_insert() { const char *c; std::string s = "ello"; - c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} - s.insert(0, 1, 'h'); // expected-note {{Inner pointer invalidated by call to 'insert'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s.insert(0, 1, 'h'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'insert'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_replace() { const char *c; std::string s = "hello world"; - c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} - s.replace(6, 5, "string"); // expected-note {{Inner pointer invalidated by call to 'replace'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s.replace(6, 5, "string"); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'replace'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_pop_back() { const char *c; std::string s; - c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} - s.pop_back(); // expected-note {{Inner pointer invalidated by call to 'pop_back'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s.pop_back(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'pop_back'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_push_back() { const char *c; std::string s; - c = s.data(); // expected-note {{Dangling inner pointer obtained here}} - s.push_back('c'); // expected-note {{Inner pointer invalidated by call to 'push_back'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s.push_back('c'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'push_back'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_reserve() { const char *c; std::string s; - c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} - s.reserve(5); // expected-note {{Inner pointer invalidated by call to 'reserve'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s.reserve(5); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'reserve'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_resize() { const char *c; std::string s; - c = s.data(); // expected-note {{Dangling inner pointer obtained here}} - s.resize(5); // expected-note {{Inner pointer invalidated by call to 'resize'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s.resize(5); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'resize'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_shrink_to_fit() { const char *c; std::string s; - c = s.data(); // expected-note {{Dangling inner pointer obtained here}} - s.shrink_to_fit(); // expected-note {{Inner pointer invalidated by call to 'shrink_to_fit'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s.shrink_to_fit(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'shrink_to_fit'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void deref_after_swap() { const char *c; std::string s1, s2; - c = s1.data(); // expected-note {{Dangling inner pointer obtained here}} - s1.swap(s2); // expected-note {{Inner pointer invalidated by call to 'swap'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s1.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + s1.swap(s2); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'swap'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} +} + +struct S { + std::string s; + const char *name() { + return s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + // expected-note@-1 {{Pointer to inner buffer of 'std::string' obtained here}} + } + void clear() { + s.clear(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'clear'}} + } + ~S() {} // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}} +}; + +void cleared_through_method() { + S x; + const char *c = x.name(); // expected-note {{Calling 'S::name'}} + // expected-note@-1 {{Returning from 'S::name'}} + x.clear(); // expected-note {{Calling 'S::clear'}} + // expected-note@-1 {{Returning; inner buffer was reallocated}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} +} + +void destroyed_through_method() { + S y; + const char *c = y.name(); // expected-note {{Calling 'S::name'}} + // expected-note@-1 {{Returning from 'S::name'}} + y.~S(); // expected-note {{Calling '~S'}} + // expected-note@-1 {{Returning; inner buffer was deallocated}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } //=---------------------------=// @@ -313,10 +311,10 @@ void deref_after_swap() { void STL_func_ref() { const char *c; std::string s; - c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} - std::func_ref(s); // expected-note {{Inner pointer invalidated by call to 'func_ref'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + std::func_ref(s); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'func_ref'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void STL_func_const_ref() { @@ -339,10 +337,10 @@ void func_ptr_known() { const char *c; std::string s; void (*func_ptr)(std::string &) = std::func_ref<std::string>; - c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} - func_ptr(s); // expected-note {{Inner pointer invalidated by call to 'func_ref'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + func_ptr(s); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'func_ref'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} } void func_ptr_unknown(void (*func_ptr)(std::string &)) { @@ -356,8 +354,44 @@ void func_ptr_unknown(void (*func_ptr)(std::string &)) { void func_default_arg() { const char *c; std::string s; - c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}} - default_arg(3, s); // expected-note {{Inner pointer invalidated by call to 'default_arg'}} - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + default_arg(3, s); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'default_arg'}} + consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}} + // expected-note@-1 {{Inner pointer of container used after re/deallocation}} +} + +struct T { + std::string to_string() { return s; } +private: + std::string s; +}; + +const char *escape_via_return_temp() { + T x; + return x.to_string().c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}} + // expected-warning@-2 {{Inner pointer of container used after re/deallocation}} + // expected-note@-3 {{Inner pointer of container used after re/deallocation}} +} + +const char *escape_via_return_local() { + std::string s; + return s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}} + // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}} + // expected-warning@-2 {{Inner pointer of container used after re/deallocation}} + // expected-note@-3 {{Inner pointer of container used after re/deallocation}} +} + + +char *c(); +class A {}; + +void no_CXXRecordDecl() { + A a, *b; + *(void **)&b = c() + 1; + *b = a; // no-crash +} + +void checkReference(std::string &s) { + const char *c = s.c_str(); } |