diff options
author | Anton Yartsev <anton.yartsev@gmail.com> | 2013-04-10 22:21:41 +0000 |
---|---|---|
committer | Anton Yartsev <anton.yartsev@gmail.com> | 2013-04-10 22:21:41 +0000 |
commit | 55e57a50a36749ce0483db2f16259649c9d25792 (patch) | |
tree | 2c9d8e3ec76d920dcd181f2c0b38107ef991076d /lib/StaticAnalyzer/Checkers/MallocChecker.cpp | |
parent | 6700b003c2a28f2a92cc41970788df6aa3273156 (diff) |
[analyzer] Switched to checkPreCall interface for detecting usage after free.
Now the check is also applied to arguments for Objective-C method calls and to 'this' pointer.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179230 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/MallocChecker.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 03471a5236..64e017ed1c 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -147,7 +147,7 @@ class MallocChecker : public Checker<check::DeadSymbols, check::PointerEscape, check::ConstPointerEscape, check::PreStmt<ReturnStmt>, - check::PreStmt<CallExpr>, + check::PreCall, check::PostStmt<CallExpr>, check::PostStmt<CXXNewExpr>, check::PreStmt<CXXDeleteExpr>, @@ -181,7 +181,7 @@ public: ChecksFilter Filter; - void checkPreStmt(const CallExpr *S, CheckerContext &C) const; + void checkPreCall(const CallEvent &Call, CheckerContext &C) const; void checkPostStmt(const CallExpr *CE, CheckerContext &C) const; void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const; void checkPreStmt(const CXXDeleteExpr *DE, CheckerContext &C) const; @@ -1671,26 +1671,39 @@ void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper, C.addTransition(state->set<RegionState>(RS), N); } -void MallocChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { +void MallocChecker::checkPreCall(const CallEvent &Call, + CheckerContext &C) const { + // We will check for double free in the post visit. - if ((Filter.CMallocOptimistic || Filter.CMallocPessimistic) && - isFreeFunction(C.getCalleeDecl(CE), C.getASTContext())) - return; + if (const AnyFunctionCall *FC = dyn_cast<AnyFunctionCall>(&Call)) { + const FunctionDecl *FD = FC->getDecl(); + if (!FD) + return; - if (Filter.CNewDeleteChecker && - isStandardNewDelete(C.getCalleeDecl(CE), C.getASTContext())) - return; + if ((Filter.CMallocOptimistic || Filter.CMallocPessimistic) && + isFreeFunction(FD, C.getASTContext())) + return; - // Check use after free, when a freed pointer is passed to a call. - ProgramStateRef State = C.getState(); - for (CallExpr::const_arg_iterator I = CE->arg_begin(), - E = CE->arg_end(); I != E; ++I) { - const Expr *A = *I; - if (A->getType().getTypePtr()->isAnyPointerType()) { - SymbolRef Sym = C.getSVal(A).getAsSymbol(); + if (Filter.CNewDeleteChecker && + isStandardNewDelete(FD, C.getASTContext())) + return; + } + + // Check if the callee of a method is deleted. + if (const CXXInstanceCall *CC = dyn_cast<CXXInstanceCall>(&Call)) { + SymbolRef Sym = CC->getCXXThisVal().getAsSymbol(); + if (!Sym || checkUseAfterFree(Sym, C, CC->getCXXThisExpr())) + return; + } + + // Check arguments for being used after free. + for (unsigned I = 0, E = Call.getNumArgs(); I != E; ++I) { + SVal ArgSVal = Call.getArgSVal(I); + if (ArgSVal.getAs<Loc>()) { + SymbolRef Sym = ArgSVal.getAsSymbol(); if (!Sym) continue; - if (checkUseAfterFree(Sym, C, A)) + if (checkUseAfterFree(Sym, C, Call.getArgExpr(I))) return; } } |