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, + check::EndFunction, check::PreCall, check::PostStmt, check::PostStmt, @@ -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(Sym); + State = State->set(E); + C.addTransition(State); + } +} + +void MallocChecker::checkEndFunction(CheckerContext &C) const { + ProgramStateRef State = C.getState(); + if (SymbolRef Sym = static_cast(State->get())) { + const Expr *E = static_cast(State->get()); checkUseAfterFree(Sym, C, E); + State = State->remove(); + State = State->remove(); + C.addTransition(State); + } } // TODO: Blocks should be either inlined or should call invalidate regions 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@-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@-1 {{Internal buffer is released because the object was destroyed}} +} // expected-warning {{Use of memory after it is freed}} +// expected-note@-1 {{Use of memory after it is freed}} + void deref_after_scope_ok(bool cond) { const char *c, *d; std::string s;