[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