void ExprEngine::processCallEnter(NodeBuilderContext& BC, CallEnter CE, ExplodedNode *Pred) { // Get the entry block in the CFG of the callee. const StackFrameContext *calleeCtx = CE.getCalleeContext(); PrettyStackTraceLocationContext CrashInfo(calleeCtx); const CFGBlock *Entry = CE.getEntry(); // Validate the CFG. assert(Entry->empty()); assert(Entry->succ_size() == 1); // Get the solitary successor. const CFGBlock *Succ = *(Entry->succ_begin()); // Construct an edge representing the starting location in the callee. BlockEdge Loc(Entry, Succ, calleeCtx); ProgramStateRef state = Pred->getState(); // Construct a new node, notify checkers that analysis of the function has // begun, and add the resultant nodes to the worklist. bool isNew; ExplodedNode *Node = G.getNode(Loc, state, false, &isNew); Node->addPredecessor(Pred, G); if (isNew) { ExplodedNodeSet DstBegin; processBeginOfFunction(BC, Node, DstBegin, Loc); Engine.enqueue(DstBegin); } }
void PathDiagnosticCallPiece::setCallee(const CallEnter &CE, const SourceManager &SM) { const StackFrameContext *CalleeCtx = CE.getCalleeContext(); Callee = CalleeCtx->getDecl(); callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM); callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM); }
PathDiagnosticPiece * UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) { ProgramStateRef State = N->getState(); ProgramPoint ProgLoc = N->getLocation(); // We are only interested in visiting CallEnter nodes. CallEnter *CEnter = dyn_cast<CallEnter>(&ProgLoc); if (!CEnter) return 0; // Check if one of the arguments is the region the visitor is tracking. CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager(); CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State); unsigned Idx = 0; for (CallEvent::param_iterator I = Call->param_begin(), E = Call->param_end(); I != E; ++I, ++Idx) { const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion(); // Are we tracking the argument or its subregion? if ( !ArgReg || (ArgReg != R && !R->isSubRegionOf(ArgReg->StripCasts()))) continue; // Check the function parameter type. const ParmVarDecl *ParamDecl = *I; assert(ParamDecl && "Formal parameter has no decl?"); QualType T = ParamDecl->getType(); if (!(T->isAnyPointerType() || T->isReferenceType())) { // Function can only change the value passed in by address. continue; } // If it is a const pointer value, the function does not intend to // change the value. if (T->getPointeeType().isConstQualified()) continue; // Mark the call site (LocationContext) as interesting if the value of the // argument is undefined or '0'/'NULL'. SVal BoundVal = State->getSVal(R); if (BoundVal.isUndef() || BoundVal.isZeroConstant()) { BR.markInteresting(CEnter->getCalleeContext()); return 0; } } return 0; }
void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) { // Get the entry block in the CFG of the callee. const StackFrameContext *calleeCtx = CE.getCalleeContext(); PrettyStackTraceLocationContext CrashInfo(calleeCtx); const CFG *CalleeCFG = calleeCtx->getCFG(); const CFGBlock *Entry = &(CalleeCFG->getEntry()); // Validate the CFG. assert(Entry->empty()); assert(Entry->succ_size() == 1); // Get the solitary successor. const CFGBlock *Succ = *(Entry->succ_begin()); // Construct an edge representing the starting location in the callee. BlockEdge Loc(Entry, Succ, calleeCtx); ProgramStateRef state = Pred->getState(); // Construct a new node and add it to the worklist. bool isNew; ExplodedNode *Node = G.getNode(Loc, state, false, &isNew); Node->addPredecessor(Pred, G); if (isNew) Engine.getWorkList()->enqueue(Node); }
void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc, const WorkListUnit& WU) { // Dispatch on the location type. switch (Loc.getKind()) { case ProgramPoint::BlockEdgeKind: HandleBlockEdge(cast<BlockEdge>(Loc), Pred); break; case ProgramPoint::BlockEntranceKind: HandleBlockEntrance(cast<BlockEntrance>(Loc), Pred); break; case ProgramPoint::BlockExitKind: assert (false && "BlockExit location never occur in forward analysis."); break; case ProgramPoint::CallEnterKind: { CallEnter CEnter = cast<CallEnter>(Loc); if (AnalyzedCallees) if (const CallExpr* CE = dyn_cast_or_null<CallExpr>(CEnter.getCallExpr())) if (const Decl *CD = CE->getCalleeDecl()) AnalyzedCallees->insert(CD); SubEng.processCallEnter(CEnter, Pred); break; } case ProgramPoint::CallExitBeginKind: SubEng.processCallExit(Pred); break; case ProgramPoint::EpsilonKind: { assert(Pred->hasSinglePred() && "Assume epsilon has exactly one predecessor by construction"); ExplodedNode *PNode = Pred->getFirstPred(); dispatchWorkItem(Pred, PNode->getLocation(), WU); break; } default: assert(isa<PostStmt>(Loc) || isa<PostInitializer>(Loc) || isa<CallExitEnd>(Loc)); HandlePostStmt(WU.getBlock(), WU.getIndex(), Pred); break; } }
void PathDiagnosticCallPiece::setCallee(const CallEnter &CE, const SourceManager &SM) { const StackFrameContext *CalleeCtx = CE.getCalleeContext(); Callee = CalleeCtx->getDecl(); callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM); callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM); // Autosynthesized property accessors are special because we'd never // pop back up to non-autosynthesized code until we leave them. // This is not generally true for autosynthesized callees, which may call // non-autosynthesized callbacks. // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag // defaults to false. if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee)) IsCalleeAnAutosynthesizedPropertyAccessor = ( MD->isPropertyAccessor() && CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized()); }
void CoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block, unsigned Index, ExplodedNode *Pred) { CallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(), L.getCalleeContext(), Block, Index); SubEng.processCallEnter(Builder); }
void CoreEngine::HandleCallEnter(const CallEnter &CE, ExplodedNode *Pred) { NodeBuilderContext BuilderCtx(*this, CE.getEntry(), Pred); SubEng.processCallEnter(BuilderCtx, CE, Pred); }