summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorReka Kovacs <rekanikolett@gmail.com>2018-07-19 15:10:06 +0000
committerReka Kovacs <rekanikolett@gmail.com>2018-07-19 15:10:06 +0000
commitc18ecc8489201b363fde22b5af1051f9ddd1dd50 (patch)
tree15f545f5123618deb9f0f0e5832fea5bbe1e4553 /clang/test
parenta2b553b4c9f48f0f2e2bb76d55d5a1407bc56eae (diff)
downloadbcm5719-llvm-c18ecc8489201b363fde22b5af1051f9ddd1dd50.tar.gz
bcm5719-llvm-c18ecc8489201b363fde22b5af1051f9ddd1dd50.zip
[analyzer] Add support for more basic_string API in
DanglingInternalBufferChecker. A pointer referring to the elements of a basic_string may be invalidated by calling a non-const member function, except operator[], at, front, back, begin, rbegin, end, and rend. The checker now warns if the pointer is used after such operations. Differential Revision: https://reviews.llvm.org/D49360 llvm-svn: 337463
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/Analysis/dangling-internal-buffer.cpp260
1 files changed, 200 insertions, 60 deletions
diff --git a/clang/test/Analysis/dangling-internal-buffer.cpp b/clang/test/Analysis/dangling-internal-buffer.cpp
index f77229c6304..fa8d5e154b9 100644
--- a/clang/test/Analysis/dangling-internal-buffer.cpp
+++ b/clang/test/Analysis/dangling-internal-buffer.cpp
@@ -2,13 +2,35 @@
namespace std {
-template< typename CharT >
+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;
@@ -23,73 +45,70 @@ void consume(const wchar_t *) {}
void consume(const char16_t *) {}
void consume(const char32_t *) {}
-void deref_after_scope_char_cstr() {
- const char *c;
+void deref_after_scope_char(bool cond) {
+ const char *c, *d;
{
std::string s;
- c = s.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}}
- } // expected-note {{Internal buffer is released because the object was destroyed}}
+ 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}}
std::string s;
const char *c2 = s.c_str();
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
-}
-
-void deref_after_scope_char_data() {
- const char *c;
- {
- std::string s;
- c = s.data(); // expected-note {{Pointer to dangling buffer was obtained here}}
- } // expected-note {{Internal buffer is released because the object was destroyed}}
- std::string s;
- const 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}}
+ if (cond) {
+ // expected-note@-1 {{Assuming 'cond' is not equal to 0}}
+ // 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}}
+ } else {
+ consume(d); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+ }
}
void deref_after_scope_char_data_non_const() {
char *c;
{
std::string s;
- c = s.data(); // expected-note {{Pointer to dangling buffer was obtained here}}
- } // expected-note {{Internal buffer is released because the object was destroyed}}
+ c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
+ } // expected-note {{Inner pointer invalidated 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}}
}
-
-void deref_after_scope_wchar_t_cstr() {
- const wchar_t *w;
+void deref_after_scope_wchar_t(bool cond) {
+ const wchar_t *c, *d;
{
- std::wstring ws;
- w = ws.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}}
- } // expected-note {{Internal buffer is released because the object was destroyed}}
- std::wstring ws;
- const wchar_t *w2 = ws.c_str();
- consume(w); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
-}
-
-void deref_after_scope_wchar_t_data() {
- const wchar_t *w;
- {
- std::wstring ws;
- w = ws.data(); // expected-note {{Pointer to dangling buffer was obtained here}}
- } // expected-note {{Internal buffer is released because the object was destroyed}}
- std::wstring ws;
- const wchar_t *w2 = ws.data();
- consume(w); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ 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}}
+ std::wstring s;
+ const wchar_t *c2 = s.c_str();
+ if (cond) {
+ // expected-note@-1 {{Assuming 'cond' is not equal to 0}}
+ // 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}}
+ } else {
+ consume(d); // expected-warning {{Use of memory after it is freed}}
+ // expected-note@-1 {{Use of memory after it is freed}}
+ }
}
void deref_after_scope_char16_t_cstr() {
const char16_t *c16;
{
std::u16string s16;
- c16 = s16.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}}
- } // expected-note {{Internal buffer is released because the object was destroyed}}
+ c16 = s16.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ } // expected-note {{Inner pointer invalidated 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}}
@@ -100,8 +119,8 @@ void deref_after_scope_char32_t_data() {
const char32_t *c32;
{
std::u32string s32;
- c32 = s32.data(); // expected-note {{Pointer to dangling buffer was obtained here}}
- } // expected-note {{Internal buffer is released because the object was destroyed}}
+ c32 = s32.data(); // expected-note {{Dangling inner pointer obtained here}}
+ } // expected-note {{Inner pointer invalidated 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}}
@@ -112,12 +131,12 @@ void multiple_symbols(bool cond) {
const char *c1, *d1;
{
std::string s1;
- c1 = s1.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}}
- d1 = s1.data(); // expected-note {{Pointer to dangling buffer was obtained here}}
+ c1 = s1.c_str(); // expected-note {{Dangling inner pointer obtained here}}
+ d1 = s1.data(); // expected-note {{Dangling inner pointer obtained here}}
const char *local = s1.c_str();
consume(local); // no-warning
- } // expected-note {{Internal buffer is released because the object was destroyed}}
- // expected-note@-1 {{Internal buffer is released because the object was destroyed}}
+ } // expected-note {{Inner pointer invalidated by call to destructor}}
+ // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
std::string s2;
const char *c2 = s2.c_str();
if (cond) {
@@ -129,23 +148,144 @@ void multiple_symbols(bool cond) {
// expected-note@-1 {{Use of memory after it is freed}}
} else {
consume(d1); // expected-warning {{Use of memory after it is freed}}
- } // expected-note@-1 {{Use of memory after it is freed}}
+ } // expected-note@-1 {{Use of memory after it is freed}}
+}
+
+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}}
+}
+
+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}}
}
-void deref_after_scope_cstr_ok() {
+void deref_after_clear() {
const char *c;
std::string s;
- {
- c = s.c_str();
- }
- consume(c); // no-warning
+ 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}}
+}
+
+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}}
+}
+
+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}}
+}
+
+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}}
}
-void deref_after_scope_data_ok() {
+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}}
+}
+
+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}}
+}
+
+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}}
+}
+
+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}}
+}
+
+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}}
+}
+
+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}}
+}
+
+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}}
+}
+
+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}}
+}
+
+void deref_after_scope_ok(bool cond) {
+ const char *c, *d;
+ std::string s;
{
- c = s.data();
+ c = s.c_str();
+ d = s.data();
}
- consume(c); // no-warning
+ if (cond)
+ consume(c); // no-warning
+ else
+ consume(d); // no-warning
}
OpenPOWER on IntegriCloud