rnkovacs created this revision.
rnkovacs added reviewers: NoQ, dcoughlin, xazax.hun, george.karpenkov.
Herald added subscribers: mikhail.ramalho, a.sidorin, dkrupp, szepet,
baloghadamsoftware, whisperity.
Following the discussion at https://reviews.llvm.org/D49360.
Added two more test cases that show "returning"-type-of notes as well.
Repository:
rC Clang
https://reviews.llvm.org/D49570
Files:
lib/StaticAnalyzer/Checkers/AllocationState.h
lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp
lib/StaticAnalyzer/Checkers/MallocChecker.cpp
test/Analysis/dangling-internal-buffer.cpp
Index: test/Analysis/dangling-internal-buffer.cpp
===================================================================
--- test/Analysis/dangling-internal-buffer.cpp
+++ test/Analysis/dangling-internal-buffer.cpp
@@ -49,232 +49,264 @@
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' object obtained here}}
+ d = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' object obtained here}}
+ } // expected-note {{Inner buffer deallocated by call to destructor}}
+ // expected-note@-1 {{Inner buffer deallocated by call to destructor}}
std::string s;
const char *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}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
} 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 {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
}
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' object obtained here}}
+ } // expected-note {{Inner buffer 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 {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ d = s.data(); // expected-note {{Pointer to inner buffer of 'std::wstring' object obtained here}}
+ } // expected-note {{Inner buffer deallocated by call to destructor}}
+ // expected-note@-1 {{Inner buffer deallocated 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}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
} 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 {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
}
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' object obtained here}}
+ } // expected-note {{Inner buffer 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 {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ } // expected-note {{Inner buffer 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 {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ d1 = s1.data(); // expected-note {{Pointer to inner buffer of 'std::string' object 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 deallocated by call to destructor}}
+ // expected-note@-1 {{Inner buffer deallocated by call to destructor}}
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}}
+ consume(c1); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
} 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 {{Deallocated pointer returned to the caller}}
+ } // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s = "world"; // expected-note {{Inner buffer reallocated by call to 'operator='}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s += " world"; // expected-note {{Inner buffer reallocated by call to 'operator+='}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s.clear(); // expected-note {{Inner buffer reallocated by call to 'clear'}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s.append(2, 'x'); // expected-note {{Inner buffer reallocated by call to 'append'}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s.assign(4, 'a'); // expected-note {{Inner buffer reallocated by call to 'assign'}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s.erase(0, 2); // expected-note {{Inner buffer reallocated by call to 'erase'}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s.insert(0, 1, 'h'); // expected-note {{Inner buffer reallocated by call to 'insert'}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s.replace(6, 5, "string"); // expected-note {{Inner buffer reallocated by call to 'replace'}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s.pop_back(); // expected-note {{Inner buffer reallocated by call to 'pop_back'}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s.push_back('c'); // expected-note {{Inner buffer reallocated by call to 'push_back'}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s.reserve(5); // expected-note {{Inner buffer reallocated by call to 'reserve'}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s.resize(5); // expected-note {{Inner buffer reallocated by call to 'resize'}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s.shrink_to_fit(); // expected-note {{Inner buffer reallocated by call to 'shrink_to_fit'}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
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' object obtained here}}
+ s1.swap(s2); // expected-note {{Inner buffer reallocated by call to 'swap'}}
+ consume(c); // expected-warning {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
+}
+
+struct S {
+ std::string s;
+ const char *name() {
+ return s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' object obtained here}}
+ // expected-note@-1 {{Pointer to inner buffer of 'std::string' object obtained here}}
+ }
+ void clear() {
+ s.clear(); // expected-note {{Inner buffer reallocated by call to 'clear'}}
+ }
+ ~S() {} // expected-note {{Inner buffer deallocated by call to destructor on 'std::string' object}}
+};
+
+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 {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
+}
+
+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 {{Deallocated pointer returned to the caller}}
+ // expected-note@-1 {{Deallocated pointer returned to the caller}}
}
void deref_after_scope_ok(bool cond) {
Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1987,15 +1987,18 @@
BT_UseFree[*CheckKind].reset(new BugType(
CheckNames[*CheckKind], "Use-after-free", categories::MemoryError));
+ AllocationFamily AF =
+ C.getState()->get<RegionState>(Sym)->getAllocationFamily();
+
auto R = llvm::make_unique<BugReport>(*BT_UseFree[*CheckKind],
- "Use of memory after it is freed", N);
+ AF == AF_InternalBuffer ? "Deallocated pointer returned to the caller"
+ : "Use of memory after it is freed", N);
R->markInteresting(Sym);
R->addRange(Range);
R->addVisitor(llvm::make_unique<MallocBugVisitor>(Sym));
- const RefState *RS = C.getState()->get<RegionState>(Sym);
- if (RS->getAllocationFamily() == AF_InternalBuffer)
+ if (AF == AF_InternalBuffer)
R->addVisitor(allocation_state::getDanglingBufferBRVisitor(Sym));
C.emitReport(std::move(R));
@@ -2903,7 +2906,7 @@
StackHintGeneratorForSymbol *StackHint = nullptr;
SmallString<256> Buf;
llvm::raw_svector_ostream OS(Buf);
-
+
if (Mode == Normal) {
if (isAllocated(RS, RSPrev, S)) {
Msg = "Memory is allocated";
@@ -2918,29 +2921,41 @@
case AF_CXXNewArray:
case AF_IfNameIndex:
Msg = "Memory is released";
+ StackHint = new StackHintGeneratorForSymbol(Sym,
+ "Returning; memory was released");
break;
case AF_InternalBuffer: {
- OS << "Inner pointer invalidated by call to ";
+ OS << "Inner buffer ";
if (N->getLocation().getKind() == ProgramPoint::PostImplicitCallKind) {
- OS << "destructor";
+ OS << "deallocated by call to destructor";
+ StackHint = new StackHintGeneratorForSymbol(Sym,
+ "Returning; inner buffer was deallocated");
} else {
- OS << "'";
+ OS << "reallocated by call to '";
const Stmt *S = RS->getStmt();
if (const auto *MemCallE = dyn_cast<CXXMemberCallExpr>(S)) {
OS << MemCallE->getMethodDecl()->getNameAsString();
} else if (const auto *OpCallE = dyn_cast<CXXOperatorCallExpr>(S)) {
OS << OpCallE->getDirectCallee()->getNameAsString();
}
OS << "'";
+ StackHint = new StackHintGeneratorForSymbol(Sym,
+ "Returning; inner buffer was reallocated");
}
+
+ // Find the type of the container object.
+ const MemRegion *ObjRegion =
+ allocation_state::getContainerObjRegion(statePrev, Sym);
+ const auto *TypedRegion = dyn_cast<TypedValueRegion>(ObjRegion);
+ QualType ObjTy = TypedRegion->getValueType();
+ OS << " on '" << ObjTy.getAsString() << "' object";
+
Msg = OS.str();
break;
}
case AF_None:
llvm_unreachable("Unhandled allocation family!");
}
- StackHint = new StackHintGeneratorForSymbol(Sym,
- "Returning; memory was released");
// See if we're releasing memory while inlining a destructor
// (or one of its callees). This turns on various common
Index: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp
+++ lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp
@@ -212,6 +212,29 @@
C.addTransition(State);
}
+namespace clang {
+namespace ento {
+namespace allocation_state {
+
+std::unique_ptr<BugReporterVisitor> getDanglingBufferBRVisitor(SymbolRef Sym) {
+ return llvm::make_unique<
+ DanglingInternalBufferChecker::DanglingBufferBRVisitor>(Sym);
+}
+
+const MemRegion *getContainerObjRegion(ProgramStateRef State, SymbolRef Sym) {
+ RawPtrMapTy Map = State->get<RawPtrMap>();
+ for (const auto Entry : Map) {
+ if (Entry.second.contains(Sym)) {
+ return Entry.first;
+ }
+ }
+ return nullptr;
+}
+
+} // end namespace allocation_state
+} // end namespace ento
+} // end namespace clang
+
std::shared_ptr<PathDiagnosticPiece>
DanglingInternalBufferChecker::DanglingBufferBRVisitor::VisitNode(
const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
@@ -225,28 +248,21 @@
if (!S)
return nullptr;
+ const MemRegion *ObjRegion =
+ allocation_state::getContainerObjRegion(N->getState(), PtrToBuf);
+ const auto *TypedRegion = dyn_cast<TypedValueRegion>(ObjRegion);
+ QualType ObjTy = TypedRegion->getValueType();
+
SmallString<256> Buf;
llvm::raw_svector_ostream OS(Buf);
- OS << "Dangling inner pointer obtained here";
+ OS << "Pointer to inner buffer of '" << ObjTy.getAsString()
+ << "' object obtained here";
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
N->getLocationContext());
return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true,
nullptr);
}
-namespace clang {
-namespace ento {
-namespace allocation_state {
-
-std::unique_ptr<BugReporterVisitor> getDanglingBufferBRVisitor(SymbolRef Sym) {
- return llvm::make_unique<
- DanglingInternalBufferChecker::DanglingBufferBRVisitor>(Sym);
-}
-
-} // end namespace allocation_state
-} // end namespace ento
-} // end namespace clang
-
void ento::registerDanglingInternalBufferChecker(CheckerManager &Mgr) {
registerNewDeleteChecker(Mgr);
Mgr.registerChecker<DanglingInternalBufferChecker>();
Index: lib/StaticAnalyzer/Checkers/AllocationState.h
===================================================================
--- lib/StaticAnalyzer/Checkers/AllocationState.h
+++ lib/StaticAnalyzer/Checkers/AllocationState.h
@@ -26,6 +26,11 @@
/// AF_InternalBuffer symbols.
std::unique_ptr<BugReporterVisitor> getDanglingBufferBRVisitor(SymbolRef Sym);
+/// 'Sym' represents a pointer to the inner buffer of a container object.
+/// This function looks up the memory region of that object in
+/// DanglingInternalBufferChecker's program state map.
+const MemRegion *getContainerObjRegion(ProgramStateRef State, SymbolRef Sym);
+
} // end namespace allocation_state
} // end namespace ento
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits