Index: include/clang/StaticAnalyzer/Core/Checker.h =================================================================== --- include/clang/StaticAnalyzer/Core/Checker.h +++ include/clang/StaticAnalyzer/Core/Checker.h @@ -321,14 +321,17 @@ const InvalidatedSymbols *invalidated, ArrayRef Explicits, ArrayRef Regions, - const CallEvent *Call) { - return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, - Explicits, Regions, Call); + const CallEvent *Call, + const LocationContext *LCtx) { + return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated, + Explicits, Regions, + Call, LCtx); } template static bool _wantsRegionChangeUpdate(void *checker, - ProgramStateRef state) { - return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state); + ProgramStateRef state, + const LocationContext *LCtx) { + return ((const CHECKER *) checker)->wantsRegionChangeUpdate(state, LCtx); } public: Index: include/clang/StaticAnalyzer/Core/CheckerManager.h =================================================================== --- include/clang/StaticAnalyzer/Core/CheckerManager.h +++ include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -323,7 +323,7 @@ ProgramPoint::Kind K); /// \brief True if at least one checker wants to check region changes. - bool wantsRegionChangeUpdate(ProgramStateRef state); + bool wantsRegionChangeUpdate(ProgramStateRef state, const LocationContext *LCtx); /// \brief Run checkers for region changes. /// @@ -341,7 +341,8 @@ const InvalidatedSymbols *invalidated, ArrayRef ExplicitRegions, ArrayRef Regions, - const CallEvent *Call); + const CallEvent *Call, + const LocationContext *LCtx); /// \brief Run checkers when pointers escape. /// @@ -449,10 +450,11 @@ const InvalidatedSymbols *symbols, ArrayRef ExplicitRegions, ArrayRef Regions, - const CallEvent *Call)> + const CallEvent *Call, + const LocationContext *LCtx)> CheckRegionChangesFunc; - typedef CheckerFn WantsRegionChangeUpdateFunc; + typedef CheckerFn WantsRegionChangeUpdateFunc; typedef CheckerFn ExplicitRegions, ArrayRef Regions, - const CallEvent *Call) override; + const CallEvent *Call, + const LocationContext *LCtx) override; /// printState - Called by ProgramStateManager to print checker-specific data. void printState(raw_ostream &Out, ProgramStateRef State, @@ -510,7 +511,9 @@ /// Call PointerEscape callback when a value escapes as a result of bind. ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, - SVal Loc, SVal Val) override; + SVal Loc, + SVal Val, + const LocationContext *LCtx) override; /// Call PointerEscape callback when a value escapes as a result of /// region invalidation. /// \param[in] ITraits Specifies invalidation traits for regions/symbols. Index: include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -230,11 +230,12 @@ ProgramStateRef bindLoc(Loc location, SVal V, + const LocationContext *LCtx, bool notifyChanges = true) const; - ProgramStateRef bindLoc(SVal location, SVal V) const; + ProgramStateRef bindLoc(SVal location, SVal V, const LocationContext *LCtx) const; - ProgramStateRef bindDefault(SVal loc, SVal V) const; + ProgramStateRef bindDefault(SVal loc, SVal V, const LocationContext *LCtx) const; ProgramStateRef killBinding(Loc LV) const; @@ -293,6 +294,10 @@ /// Get the lvalue for an array index. SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const; + /// Get the symbolic value of arguments used in a call + /// that created the given stack frame + SVal getArgSVal(const StackFrameContext *SFC, const unsigned ArgIdx) const; + /// Returns the SVal bound to the statement 'S' in the state's environment. SVal getSVal(const Stmt *S, const LocationContext *LCtx) const; @@ -684,9 +689,9 @@ ->assumeWithinInclusiveRangeDual(this, Val.castAs(), From, To); } -inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const { +inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V, const LocationContext *LCtx) const { if (Optional L = LV.getAs()) - return bindLoc(*L, V); + return bindLoc(*L, V, LCtx); return this; } @@ -724,6 +729,28 @@ return UnknownVal(); } +inline SVal ProgramState::getArgSVal(const StackFrameContext *SFC, + const unsigned ArgIdx) const { + const FunctionDecl *FunctionDecl = SFC->getDecl()->getAsFunction(); + unsigned NumArgs = FunctionDecl->getNumParams(); + assert(ArgIdx < NumArgs && "Arg access out of range!"); + + if (SFC->inTopFrame()) { + // if we are in the top frame we don't have any arguments bound in the store + // because the call wasn't modeled in the first place. + const VarDecl *ArgDecl = FunctionDecl->parameters()[ArgIdx]; + const Loc ArgLoc = getLValue(ArgDecl, SFC); + return getSVal(ArgLoc); + } else { + // in this case we need to ask the environment as the arguments' memory + // region may have been purged as no longer needed. + const Stmt *callSite = SFC->getCallSite(); + const CallExpr *callSiteExpr = dyn_cast(callSite); + const Expr *argExpr = callSiteExpr->getArg(ArgIdx); + return getSVal(argExpr, SFC->getParent()); + } +} + inline SVal ProgramState::getSVal(const Stmt *Ex, const LocationContext *LCtx) const{ return Env.getSVal(EnvironmentEntry(Ex, LCtx), Index: include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -126,7 +126,8 @@ /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a /// region change should trigger a processRegionChanges update. - virtual bool wantsRegionChangeUpdate(ProgramStateRef state) = 0; + virtual bool wantsRegionChangeUpdate(ProgramStateRef state, + const LocationContext *LCtx) = 0; /// processRegionChanges - Called by ProgramStateManager whenever a change is /// made to the store. Used to update checkers that track region values. @@ -135,17 +136,19 @@ const InvalidatedSymbols *invalidated, ArrayRef ExplicitRegions, ArrayRef Regions, - const CallEvent *Call) = 0; + const CallEvent *Call, + const LocationContext *LCtx) = 0; inline ProgramStateRef processRegionChange(ProgramStateRef state, - const MemRegion* MR) { - return processRegionChanges(state, nullptr, MR, MR, nullptr); + const MemRegion* MR, + const LocationContext *LCtx) { + return processRegionChanges(state, nullptr, MR, MR, nullptr, LCtx); } virtual ProgramStateRef - processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val) = 0; + processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val, const LocationContext *LCtx) = 0; virtual ProgramStateRef notifyCheckersOfPointerEscape(ProgramStateRef State, Index: lib/StaticAnalyzer/Checkers/CStringChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -62,14 +62,15 @@ void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const; void checkLiveSymbols(ProgramStateRef state, SymbolReaper &SR) const; void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; - bool wantsRegionChangeUpdate(ProgramStateRef state) const; + bool wantsRegionChangeUpdate(ProgramStateRef state, const LocationContext *LCtx) const; ProgramStateRef checkRegionChanges(ProgramStateRef state, const InvalidatedSymbols *, ArrayRef ExplicitRegions, ArrayRef Regions, - const CallEvent *Call) const; + const CallEvent *Call, + const LocationContext *LCtx) const; typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *) const; @@ -1944,8 +1945,12 @@ // Overwrite the search string pointer. The new value is either an address // further along in the same string, or NULL if there are no more tokens. State = State->bindLoc(*SearchStrLoc, - SVB.conjureSymbolVal(getTag(), CE, LCtx, CharPtrTy, - C.blockCount())); + SVB.conjureSymbolVal(getTag(), + CE, + LCtx, + CharPtrTy, + C.blockCount()), + LCtx); } else { assert(SearchStrVal.isUnknown()); // Conjure a symbolic value. It's the best we can do. @@ -2112,7 +2117,8 @@ C.addTransition(state); } -bool CStringChecker::wantsRegionChangeUpdate(ProgramStateRef state) const { +bool CStringChecker::wantsRegionChangeUpdate(ProgramStateRef state, + const LocationContext *LCtx) const { CStringLengthTy Entries = state->get(); return !Entries.isEmpty(); } @@ -2122,7 +2128,8 @@ const InvalidatedSymbols *, ArrayRef ExplicitRegions, ArrayRef Regions, - const CallEvent *Call) const { + const CallEvent *Call, + const LocationContext *LCtx) const { CStringLengthTy Entries = state->get(); if (Entries.isEmpty()) return state; Index: lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp +++ lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp @@ -51,9 +51,9 @@ State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame())); auto Param = SVB.makeLoc(State->getRegion(MD->getParamDecl(0), LCtx)); auto ParamVal = State->getSVal(Param); - ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal); + ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal, LCtx); C.addTransition(SelfAssignState); - ProgramStateRef NonSelfAssignState = State->bindLoc(Param, ParamVal); + ProgramStateRef NonSelfAssignState = State->bindLoc(Param, ParamVal, LCtx); C.addTransition(NonSelfAssignState); } Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -1155,7 +1155,7 @@ State = State->BindExpr(CE, C.getLocationContext(), RetVal); // Fill the region with the initialization value. - State = State->bindDefault(RetVal, Init); + State = State->bindDefault(RetVal, Init, LCtx); // Set the region's extent equal to the Size parameter. const SymbolicRegion *R = Index: lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -2647,9 +2647,10 @@ const InvalidatedSymbols *invalidated, ArrayRef ExplicitRegions, ArrayRef Regions, - const CallEvent *Call) const; + const CallEvent *Call, + const LocationContext* LCtx) const; - bool wantsRegionChangeUpdate(ProgramStateRef state) const { + bool wantsRegionChangeUpdate(ProgramStateRef state, const LocationContext *LCtx) const { return true; } @@ -3638,7 +3639,7 @@ // same state. SVal StoredVal = state->getSVal(regionLoc->getRegion()); if (StoredVal != val) - escapes = (state == (state->bindLoc(*regionLoc, val))); + escapes = (state == (state->bindLoc(*regionLoc, val, C.getLocationContext()))); } if (!escapes) { // Case 4: We do not currently model what happens when a symbol is @@ -3708,7 +3709,8 @@ const InvalidatedSymbols *invalidated, ArrayRef ExplicitRegions, ArrayRef Regions, - const CallEvent *Call) const { + const CallEvent *Call, + const LocationContext *LCtx) const { if (!invalidated) return state; Index: lib/StaticAnalyzer/Core/CheckerManager.cpp =================================================================== --- lib/StaticAnalyzer/Core/CheckerManager.cpp +++ lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -519,9 +519,9 @@ } /// \brief True if at least one checker wants to check region changes. -bool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) { +bool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state, const LocationContext *LCtx) { for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) - if (RegionChangesCheckers[i].WantUpdateFn(state)) + if (RegionChangesCheckers[i].WantUpdateFn(state, LCtx)) return true; return false; @@ -533,14 +533,16 @@ const InvalidatedSymbols *invalidated, ArrayRef ExplicitRegions, ArrayRef Regions, - const CallEvent *Call) { + const CallEvent *Call, + const LocationContext *LCtx) { for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { // If any checker declares the state infeasible (or if it starts that way), // bail out. if (!state) return nullptr; state = RegionChangesCheckers[i].CheckFn(state, invalidated, - ExplicitRegions, Regions, Call); + ExplicitRegions, Regions, + Call, LCtx); } return state; } Index: lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -238,7 +238,7 @@ if (V.isUnknown()) V = getSValBuilder().conjureSymbolVal(Result, LC, TR->getValueType(), currBldrCtx->blockCount()); - State = State->bindLoc(Reg, V); + State = State->bindLoc(Reg, V, LC); // Re-apply the casts (from innermost to outermost) for type sanity. for (SmallVectorImpl::reverse_iterator I = Casts.rbegin(), @@ -262,8 +262,9 @@ return getCheckerManager().runCheckersForEvalAssume(state, cond, assumption); } -bool ExprEngine::wantsRegionChangeUpdate(ProgramStateRef state) { - return getCheckerManager().wantsRegionChangeUpdate(state); +bool ExprEngine::wantsRegionChangeUpdate(ProgramStateRef state, + const LocationContext *LCtx) { + return getCheckerManager().wantsRegionChangeUpdate(state, LCtx); } ProgramStateRef @@ -271,9 +272,11 @@ const InvalidatedSymbols *invalidated, ArrayRef Explicits, ArrayRef Regions, - const CallEvent *Call) { + const CallEvent *Call, + const LocationContext *LCtx) { return getCheckerManager().runCheckersForRegionChanges(state, invalidated, - Explicits, Regions, Call); + Explicits, Regions, + Call, LCtx); } void ExprEngine::printState(raw_ostream &Out, ProgramStateRef State, @@ -2133,7 +2136,9 @@ // (3) We are binding to a MemRegion with stack storage that the store // does not understand. ProgramStateRef ExprEngine::processPointerEscapedOnBind(ProgramStateRef State, - SVal Loc, SVal Val) { + SVal Loc, + SVal Val, + const LocationContext *LCtx) { // Are we storing to something that causes the value to "escape"? bool escapes = true; @@ -2149,7 +2154,7 @@ // same state. SVal StoredVal = State->getSVal(regionLoc->getRegion()); if (StoredVal != Val) - escapes = (State == (State->bindLoc(*regionLoc, Val))); + escapes = (State == (State->bindLoc(*regionLoc, Val, LCtx))); } } @@ -2246,7 +2251,7 @@ const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/nullptr, /*tag*/nullptr); ProgramStateRef state = Pred->getState(); - state = processPointerEscapedOnBind(state, location, Val); + state = processPointerEscapedOnBind(state, location, Val, LC); Bldr.generateNode(L, state, Pred); return; } @@ -2256,13 +2261,13 @@ ExplodedNode *PredI = *I; ProgramStateRef state = PredI->getState(); - state = processPointerEscapedOnBind(state, location, Val); + state = processPointerEscapedOnBind(state, location, Val, LC); // When binding the value, pass on the hint that this is a initialization. // For initializations, we do not need to inform clients of region // changes. state = state->bindLoc(location.castAs(), - Val, /* notifyChanges = */ !atDeclInit); + Val, LC, /* notifyChanges = */ !atDeclInit); const MemRegion *LocReg = nullptr; if (Optional LocRegVal = @@ -2488,7 +2493,7 @@ assert (!X.getAs()); // Should be an Lval, or unknown, undef. if (Optional LV = X.getAs()) - state = state->bindLoc(*LV, UnknownVal()); + state = state->bindLoc(*LV, UnknownVal(), Pred->getLocationContext()); } Bldr.generateNode(A, Pred, state); Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -226,12 +226,13 @@ if (capturedR != originalR) { SVal originalV; + const LocationContext *LCtx = Pred->getLocationContext(); if (copyExpr) { - originalV = State->getSVal(copyExpr, Pred->getLocationContext()); + originalV = State->getSVal(copyExpr, LCtx); } else { originalV = State->getSVal(loc::MemRegionVal(originalR)); } - State = State->bindLoc(loc::MemRegionVal(capturedR), originalV); + State = State->bindLoc(loc::MemRegionVal(capturedR), originalV, LCtx); } } } @@ -478,7 +479,7 @@ } else { assert(isa(Init)); Loc CLLoc = State->getLValue(CL, LCtx); - State = State->bindLoc(CLLoc, V); + State = State->bindLoc(CLLoc, V, LCtx); // Compound literal expressions are a GNU extension in C++. // Unlike in C, where CLs are lvalues, in C++ CLs are prvalues, Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -317,7 +317,7 @@ // actually make things worse. Placement new makes this tricky as well, // since it's then possible to be initializing one part of a multi- // dimensional array. - State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal); + State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal, LCtx); Bldr.generateNode(CE, *I, State, /*tag=*/nullptr, ProgramPoint::PreStmtKind); } @@ -548,7 +548,7 @@ SVal V = svalBuilder.conjureSymbolVal(CS, LCtx, VD->getType(), currBldrCtx->blockCount()); ProgramStateRef state = Pred->getState(); - state = state->bindLoc(state->getLValue(VD, LCtx), V); + state = state->bindLoc(state->getLValue(VD, LCtx), V, LCtx); StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); Bldr.generateNode(CS, Pred, state); @@ -603,7 +603,7 @@ InitVal = State->getSVal(SizeExpr, LocCtxt); } - State = State->bindLoc(FieldLoc, InitVal); + State = State->bindLoc(FieldLoc, InitVal, LocCtxt); } // Decay the Loc into an RValue, because there might be a Index: lib/StaticAnalyzer/Core/ExprEngineObjC.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineObjC.cpp +++ lib/StaticAnalyzer/Core/ExprEngineObjC.cpp @@ -115,11 +115,11 @@ SymbolRef Sym = SymMgr.conjureSymbol(elem, LCtx, T, currBldrCtx->blockCount()); SVal V = svalBuilder.makeLoc(Sym); - hasElems = hasElems->bindLoc(elementV, V); + hasElems = hasElems->bindLoc(elementV, V, LCtx); // Bind the location to 'nil' on the false branch. SVal nilV = svalBuilder.makeIntVal(0, T); - noElems = noElems->bindLoc(elementV, nilV); + noElems = noElems->bindLoc(elementV, nilV, LCtx); } // Create the new nodes. Index: lib/StaticAnalyzer/Core/ProgramState.cpp =================================================================== --- lib/StaticAnalyzer/Core/ProgramState.cpp +++ lib/StaticAnalyzer/Core/ProgramState.cpp @@ -111,24 +111,29 @@ return ConstraintMgr->removeDeadBindings(Result, SymReaper); } -ProgramStateRef ProgramState::bindLoc(Loc LV, SVal V, bool notifyChanges) const { +ProgramStateRef ProgramState::bindLoc(Loc LV, + SVal V, + const LocationContext *LCtx, + bool notifyChanges) const { ProgramStateManager &Mgr = getStateManager(); ProgramStateRef newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(), LV, V)); const MemRegion *MR = LV.getAsRegion(); if (MR && Mgr.getOwningEngine() && notifyChanges) - return Mgr.getOwningEngine()->processRegionChange(newState, MR); + return Mgr.getOwningEngine()->processRegionChange(newState, MR, LCtx); return newState; } -ProgramStateRef ProgramState::bindDefault(SVal loc, SVal V) const { +ProgramStateRef ProgramState::bindDefault(SVal loc, + SVal V, + const LocationContext *LCtx) const { ProgramStateManager &Mgr = getStateManager(); const MemRegion *R = loc.castAs().getRegion(); const StoreRef &newStore = Mgr.StoreMgr->BindDefault(getStore(), R, V); ProgramStateRef new_state = makeWithStore(newStore); return Mgr.getOwningEngine() ? - Mgr.getOwningEngine()->processRegionChange(new_state, R) : + Mgr.getOwningEngine()->processRegionChange(new_state, R, LCtx) : new_state; } @@ -202,7 +207,7 @@ } return Eng->processRegionChanges(newState, IS, TopLevelInvalidated, - Invalidated, Call); + Invalidated, Call, LCtx); } const StoreRef &newStore =