diff options
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/MallocChecker.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index b4e45a29d6..57666499c4 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -134,6 +134,7 @@ typedef std::pair<const ExplodedNode*, const MemRegion*> LeakInfo; class MallocChecker : public Checker<check::DeadSymbols, check::PointerEscape, + check::ConstPointerEscape, check::PreStmt<ReturnStmt>, check::PreStmt<CallExpr>, check::PostStmt<CallExpr>, @@ -185,6 +186,10 @@ public: const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind) const; + ProgramStateRef checkConstPointerEscape(ProgramStateRef State, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, + PointerEscapeKind Kind) const; void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const; @@ -270,6 +275,13 @@ private: bool doesNotFreeMemOrInteresting(const CallEvent *Call, ProgramStateRef State) const; + // Implementation of the checkPointerEscape callabcks. + ProgramStateRef checkPointerEscapeAux(ProgramStateRef State, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, + PointerEscapeKind Kind, + bool(*CheckRefState)(const RefState*)) const; + static bool SummarizeValue(raw_ostream &os, SVal V); static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR); void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange Range, @@ -1865,10 +1877,35 @@ bool MallocChecker::doesNotFreeMemOrInteresting(const CallEvent *Call, return true; } +static bool retTrue(const RefState *RS) { + return true; +} + +static bool checkIfNewOrNewArrayFamily(const RefState *RS) { + return (RS->getAllocationFamily() == AF_CXXNewArray || + RS->getAllocationFamily() == AF_CXXNew); +} + ProgramStateRef MallocChecker::checkPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind) const { + return checkPointerEscapeAux(State, Escaped, Call, Kind, &retTrue); +} + +ProgramStateRef MallocChecker::checkConstPointerEscape(ProgramStateRef State, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, + PointerEscapeKind Kind) const { + return checkPointerEscapeAux(State, Escaped, Call, Kind, + &checkIfNewOrNewArrayFamily); +} + +ProgramStateRef MallocChecker::checkPointerEscapeAux(ProgramStateRef State, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, + PointerEscapeKind Kind, + bool(*CheckRefState)(const RefState*)) const { // If we know that the call does not free memory, or we want to process the // call later, keep tracking the top level arguments. if ((Kind == PSK_DirectEscapeOnCall || @@ -1878,12 +1915,12 @@ ProgramStateRef MallocChecker::checkPointerEscape(ProgramStateRef State, } for (InvalidatedSymbols::const_iterator I = Escaped.begin(), - E = Escaped.end(); - I != E; ++I) { + E = Escaped.end(); + I != E; ++I) { SymbolRef sym = *I; if (const RefState *RS = State->get<RegionState>(sym)) { - if (RS->isAllocated()) + if (RS->isAllocated() && CheckRefState(RS)) State = State->remove<RegionState>(sym); } } |