From a14c1d09f6720c46396e2e0537807267affeb418 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Tue, 13 Nov 2012 19:47:40 +0000 Subject: [analyzer] Address Jordan's code review for r167813. This simplifies logic, fixes a bug, and adds a test case. Thanks Jordan! llvm-svn: 167868 --- .../lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 35 ++++++++++------------ 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp') diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 887f3878f2e..caf70ca3706 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -627,24 +627,19 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, ReleasedAllocated, ReturnsNullOnFailure); } -/// Check if the previous call to free on the given symbol failed. -/// -/// For example, if free failed, returns true. In addition, cleans out the -/// state from the corresponding failure info. Retuns the cleaned out state -/// and the corresponding return value symbol. -static std::pair -checkAndCleanFreeFailedInfo(ProgramStateRef State, - SymbolRef Sym, const SymbolRef *Ret) { - Ret = State->get(Sym); +/// Checks if the previous call to free on the given symbol failed - if free +/// failed, returns true. Also, returns the corresponding return value symbol. +bool didPreviousFreeFail(ProgramStateRef State, + SymbolRef Sym, SymbolRef &RetStatusSymbol) { + const SymbolRef *Ret = State->get(Sym); if (Ret) { assert(*Ret && "We should not store the null return symbol"); ConstraintManager &CMgr = State->getConstraintManager(); ConditionTruthVal FreeFailed = CMgr.isNull(State, *Ret); - State = State->remove(Sym); - return std::pair(FreeFailed.isConstrainedTrue(), - State); + RetStatusSymbol = *Ret; + return FreeFailed.isConstrainedTrue(); } - return std::pair(false, State); + return false; } ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, @@ -716,15 +711,12 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, SymbolRef Sym = SR->getSymbol(); const RefState *RS = State->get(Sym); - bool FailedToFree = false; - const SymbolRef *RetStatusSymbolPtr = 0; - llvm::tie(FailedToFree, State) = - checkAndCleanFreeFailedInfo(State, Sym, RetStatusSymbolPtr); + SymbolRef PreviousRetStatusSymbol = 0; // Check double free. if (RS && (RS->isReleased() || RS->isRelinquished()) && - !FailedToFree) { + !didPreviousFreeFail(State, Sym, PreviousRetStatusSymbol)) { if (ExplodedNode *N = C.generateSink()) { if (!BT_DoubleFree) @@ -735,8 +727,8 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, "Attempt to free non-owned memory"), N); R->addRange(ArgExpr->getSourceRange()); R->markInteresting(Sym); - if (RetStatusSymbolPtr) - R->markInteresting(*RetStatusSymbolPtr); + if (PreviousRetStatusSymbol) + R->markInteresting(PreviousRetStatusSymbol); R->addVisitor(new MallocBugVisitor(Sym)); C.emitReport(R); } @@ -745,6 +737,9 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C, ReleasedAllocated = (RS != 0); + // Clean out the info on previous call to free return info. + State = State->remove(Sym); + // Keep track of the return value. If it is NULL, we will know that free // failed. if (ReturnsNullOnFailure) { -- cgit v1.2.3