[PATCH] D49361: [analyzer][WIP] Detect pointers escaped after return statement execution in MallocChecker

Reka Kovacs via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Sun Jul 15 21:48:30 PDT 2018


rnkovacs created this revision.
rnkovacs added reviewers: NoQ, xazax.hun, george.karpenkov.
Herald added subscribers: mikhail.ramalho, a.sidorin, dkrupp, szepet, baloghadamsoftware, whisperity.

Sometimes an object is destroyed right after the statement returning it is executed. This patch aims to make MallocChecker warn for these cases as well.

FIXME1: Using two traits might not be the best solution.
FIXME2: The warning is emitted at the end of the function, which might be confusing.


Repository:
  rC Clang

https://reviews.llvm.org/D49361

Files:
  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
@@ -277,6 +277,13 @@
   // expected-note at -1 {{Use of memory after it is freed}}
 }
 
+const char *escape_via_return() {
+  std::string s;
+  return s.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}}
+                    // expected-note at -1 {{Internal buffer is released because the object was destroyed}}
+} // 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(bool cond) {
   const char *c, *d;
   std::string s;
Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -161,6 +161,7 @@
                                      check::PointerEscape,
                                      check::ConstPointerEscape,
                                      check::PreStmt<ReturnStmt>,
+                                     check::EndFunction,
                                      check::PreCall,
                                      check::PostStmt<CallExpr>,
                                      check::PostStmt<CXXNewExpr>,
@@ -217,6 +218,7 @@
   void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
   void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
   void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
+  void checkEndFunction(CheckerContext &C) const;
   ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
                             bool Assumption) const;
   void checkLocation(SVal l, bool isLoad, const Stmt *S,
@@ -556,12 +558,16 @@
     };
   };
 };
+
 } // end anonymous namespace
 
 REGISTER_MAP_WITH_PROGRAMSTATE(RegionState, SymbolRef, RefState)
 REGISTER_MAP_WITH_PROGRAMSTATE(ReallocPairs, SymbolRef, ReallocPair)
 REGISTER_SET_WITH_PROGRAMSTATE(ReallocSizeZeroSymbols, SymbolRef)
 
+REGISTER_TRAIT_WITH_PROGRAMSTATE(ReturnValue, const void *)
+REGISTER_TRAIT_WITH_PROGRAMSTATE(ReturnExpr, const void *)
+
 // A map from the freed symbol to the symbol representing the return value of
 // the free function.
 REGISTER_MAP_WITH_PROGRAMSTATE(FreeReturnValue, SymbolRef, SymbolRef)
@@ -2471,8 +2477,22 @@
           Sym = BMR->getSymbol();
 
   // Check if we are returning freed memory.
-  if (Sym)
+  if (Sym) {
+    State = State->set<ReturnValue>(Sym);
+    State = State->set<ReturnExpr>(E);
+    C.addTransition(State);
+  }
+}
+
+void MallocChecker::checkEndFunction(CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  if (SymbolRef Sym = static_cast<SymbolRef>(State->get<ReturnValue>())) {
+    const Expr *E = static_cast<const Expr *>(State->get<ReturnExpr>());
     checkUseAfterFree(Sym, C, E);
+    State = State->remove<ReturnValue>();
+    State = State->remove<ReturnExpr>();
+    C.addTransition(State);
+  }
 }
 
 // TODO: Blocks should be either inlined or should call invalidate regions


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D49361.155614.patch
Type: text/x-patch
Size: 3196 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180716/9795cfaa/attachment-0001.bin>


More information about the cfe-commits mailing list