r336497 - [analyzer] Add support for data() in DanglingInternalBufferChecker.
Reka Kovacs via cfe-commits
cfe-commits at lists.llvm.org
Sat Jul 7 13:29:24 PDT 2018
Author: rkovacs
Date: Sat Jul 7 13:29:24 2018
New Revision: 336497
URL: http://llvm.org/viewvc/llvm-project?rev=336497&view=rev
Log:
[analyzer] Add support for data() in DanglingInternalBufferChecker.
DanglingInternalBufferChecker now tracks use-after-free problems related
to the incorrect usage of std::basic_string::data().
Differential Revision: https://reviews.llvm.org/D48532
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp
cfe/trunk/test/Analysis/dangling-internal-buffer.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp?rev=336497&r1=336496&r2=336497&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp Sat Jul 7 13:29:24 2018
@@ -24,15 +24,16 @@
using namespace clang;
using namespace ento;
-// FIXME: c_str() may be called on a string object many times, so it should
-// have a list of symbols associated with it.
+// FIXME: member functions that return a pointer to the container's internal
+// buffer may be called on the object many times, so the object's memory
+// region should have a list of pointer symbols associated with it.
REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, SymbolRef)
namespace {
class DanglingInternalBufferChecker
: public Checker<check::DeadSymbols, check::PostCall> {
- CallDescription CStrFn;
+ CallDescription CStrFn, DataFn;
public:
class DanglingBufferBRVisitor : public BugReporterVisitor {
@@ -67,7 +68,7 @@ public:
}
};
- DanglingInternalBufferChecker() : CStrFn("c_str") {}
+ DanglingInternalBufferChecker() : CStrFn("c_str"), DataFn("data") {}
/// Record the connection between the symbol returned by c_str() and the
/// corresponding string object region in the ProgramState. Mark the symbol
@@ -97,7 +98,7 @@ void DanglingInternalBufferChecker::chec
ProgramStateRef State = C.getState();
- if (Call.isCalled(CStrFn)) {
+ if (Call.isCalled(CStrFn) || Call.isCalled(DataFn)) {
SVal RawPtr = Call.getReturnValue();
if (!RawPtr.isUnknown()) {
State = State->set<RawPtrMap>(TypedR, RawPtr.getAsSymbol());
Modified: cfe/trunk/test/Analysis/dangling-internal-buffer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dangling-internal-buffer.cpp?rev=336497&r1=336496&r2=336497&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/dangling-internal-buffer.cpp (original)
+++ cfe/trunk/test/Analysis/dangling-internal-buffer.cpp Sat Jul 7 13:29:24 2018
@@ -7,6 +7,8 @@ class basic_string {
public:
~basic_string();
const CharT *c_str() const;
+ const CharT *data() const;
+ CharT *data();
};
typedef basic_string<char> string;
@@ -21,59 +23,92 @@ void consume(const wchar_t *) {}
void consume(const char16_t *) {}
void consume(const char32_t *) {}
-void deref_after_scope_char() {
+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 at -1 {{Use of memory after it is freed}}
}
-void deref_after_scope_char2() {
+void deref_after_scope_char_data() {
const char *c;
{
std::string s;
- c = s.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}}
+ 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.c_str();
+ const char *c2 = s.data();
+ consume(c); // expected-warning {{Use of memory after it is freed}}
+ // expected-note at -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 at -1 {{Use of memory after it is freed}}
}
-void deref_after_scope_wchar_t() {
+
+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 at -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 at -1 {{Use of memory after it is freed}}
}
-void deref_after_scope_char16_t() {
+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 at -1 {{Use of memory after it is freed}}
}
-void deref_after_scope_char32_t() {
+void deref_after_scope_char32_t_data() {
const char32_t *c32;
{
std::u32string s32;
- c32 = s32.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}}
+ 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 at -1 {{Use of memory after it is freed}}
}
-void deref_after_scope_ok() {
+void deref_after_scope_cstr_ok() {
const char *c;
std::string s;
{
@@ -81,3 +116,12 @@ void deref_after_scope_ok() {
}
consume(c); // no-warning
}
+
+void deref_after_scope_data_ok() {
+ const char *c;
+ std::string s;
+ {
+ c = s.data();
+ }
+ consume(c); // no-warning
+}
More information about the cfe-commits
mailing list