rnkovacs created this revision.
rnkovacs added reviewers: NoQ, xazax.hun, george.karpenkov, dcoughlin.
Herald added subscribers: mikhail.ramalho, a.sidorin, dkrupp, szepet,
baloghadamsoftware, whisperity.
Add a bug visitor to `DanglingInternalBuffer` checker that places a note at the
point where the dangling pointer was obtained.
The visitor is handed over to `MallocChecker` and attached to the report there.
Repository:
rC Clang
https://reviews.llvm.org/D48522
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
@@ -25,7 +25,7 @@
const char *c;
{
std::string s;
- c = s.c_str();
+ c = s.c_str(); // expected-note {{Dangling buffer was obtained here}}
} // expected-note {{Internal buffer is released because the object was destroyed}}
consume(c); // expected-warning {{Use of memory after it is freed}}
// expected-note@-1 {{Use of memory after it is freed}}
@@ -35,7 +35,7 @@
const wchar_t *w;
{
std::wstring ws;
- w = ws.c_str();
+ w = ws.c_str(); // expected-note {{Dangling buffer was obtained here}}
} // expected-note {{Internal buffer is released because the object was destroyed}}
consume(w); // expected-warning {{Use of memory after it is freed}}
// expected-note@-1 {{Use of memory after it is freed}}
@@ -45,7 +45,7 @@
const char16_t *c16;
{
std::u16string s16;
- c16 = s16.c_str();
+ c16 = s16.c_str(); // expected-note {{Dangling buffer was obtained here}}
} // expected-note {{Internal buffer is released because the object was destroyed}}
consume(c16); // expected-warning {{Use of memory after it is freed}}
// expected-note@-1 {{Use of memory after it is freed}}
@@ -55,7 +55,7 @@
const char32_t *c32;
{
std::u32string s32;
- c32 = s32.c_str();
+ c32 = s32.c_str(); // expected-note {{Dangling buffer was obtained here}}
} // expected-note {{Internal buffer is released because the object was destroyed}}
consume(c32); // expected-warning {{Use of memory after it is freed}}
// expected-note@-1 {{Use of memory after it is freed}}
Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1988,6 +1988,11 @@
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)
+ R->addVisitor(allocation_state::getDanglingBufferBRVisitor());
+
C.emitReport(std::move(R));
}
}
Index: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp
+++ lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp
@@ -31,6 +31,28 @@
CallDescription CStrFn;
public:
+ class DanglingBufferBRVisitor
+ : public BugReporterVisitorImpl<DanglingBufferBRVisitor> {
+ bool Satisfied;
+
+ public:
+ DanglingBufferBRVisitor() : Satisfied(false) {}
+
+ static void *getTag() {
+ static int Tag = 0;
+ return &Tag;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override {
+ ID.AddPointer(getTag());
+ }
+
+ std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+ };
+
DanglingInternalBufferChecker() : CStrFn("c_str") {}
/// Record the connection between the symbol returned by c_str() and the
@@ -103,6 +125,54 @@
C.addTransition(State);
}
+std::shared_ptr<PathDiagnosticPiece>
+DanglingInternalBufferChecker::DanglingBufferBRVisitor::VisitNode(
+ const ExplodedNode *N, const ExplodedNode *PrevN,
+ BugReporterContext &BRC, BugReport &BR) {
+ if (Satisfied)
+ return nullptr;
+
+ const Stmt *S = PathDiagnosticLocation::getStmt(N);
+ const auto *MemberCallExpr = dyn_cast_or_null<CXXMemberCallExpr>(S);
+ if (!MemberCallExpr)
+ return nullptr;
+
+ const Decl *D = MemberCallExpr->getCalleeDecl();
+ const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
+ if (!FD)
+ return nullptr;
+
+ const IdentifierInfo *FunI = FD->getIdentifier();
+ if (!FunI)
+ return nullptr;
+
+ if (!(FunI->getName() == "c_str"))
+ return nullptr;
+
+ Satisfied = true;
+
+ SmallString<256> Buf;
+ llvm::raw_svector_ostream OS(Buf);
+ OS << "Dangling buffer was obtained here";
+ PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+ N->getLocationContext());
+ return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(),
+ /*addPosRange=*/true,
+ /*(*stackHint)=*/nullptr);
+}
+
+namespace clang {
+namespace ento {
+namespace allocation_state {
+
+std::unique_ptr<BugReporterVisitor> getDanglingBufferBRVisitor() {
+ return llvm::make_unique<DanglingInternalBufferChecker::DanglingBufferBRVisitor>();
+}
+
+} // 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
@@ -20,6 +20,8 @@
ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym,
const Expr *Origin);
+std::unique_ptr<BugReporterVisitor> getDanglingBufferBRVisitor();
+
} // end namespace allocation_state
} // end namespace ento
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits