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
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to