1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | //RUN: %clang_analyze_cc1 -analyzer-checker=alpha.cplusplus.DanglingInternalBuffer %s -analyzer-output=text -verify namespace std { template< typename CharT > class basic_string { public: ~basic_string(); const CharT *c_str() const; const CharT *data() const; CharT *data(); }; typedef basic_string<char> string; typedef basic_string<wchar_t> wstring; typedef basic_string<char16_t> u16string; typedef basic_string<char32_t> u32string; } // end namespace std void consume(const char *) {} void consume(const wchar_t *) {} void consume(const char16_t *) {} void consume(const char32_t *) {} void deref_after_scope_char_cstr() { const char *c; { 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}} 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}} } 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}} 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; { 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}} } 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}} 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}} } 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}} 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}} } 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}} 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}} std::string s2; const char *c2 = s2.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(c1); // expected-warning {{Use of memory after it is freed}} // 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}} } void deref_after_scope_cstr_ok() { const char *c; std::string s; { c = s.c_str(); } consume(c); // no-warning } void deref_after_scope_data_ok() { const char *c; std::string s; { c = s.data(); } consume(c); // no-warning } |