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 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); }
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); }