StoreManager::StoreManager(ProgramStateManager &stateMgr) : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr), MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {}
std::unique_ptr<ConstraintManager> ento::CreateRangeConstraintManager(ProgramStateManager &StMgr, SubEngine *Eng) { return llvm::make_unique<RangeConstraintManager>(Eng, StMgr.getSValBuilder()); }
static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr, const ExplodedNode *N, SymbolRef Sym) { const ExplodedNode *AllocationNode = N; const ExplodedNode *AllocationNodeInCurrentOrParentContext = N; const MemRegion *FirstBinding = nullptr; const LocationContext *LeakContext = N->getLocationContext(); // The location context of the init method called on the leaked object, if // available. const LocationContext *InitMethodContext = nullptr; while (N) { ProgramStateRef St = N->getState(); const LocationContext *NContext = N->getLocationContext(); if (!getRefBinding(St, Sym)) break; StoreManager::FindUniqueBinding FB(Sym); StateMgr.iterBindings(St, FB); if (FB) { const MemRegion *R = FB.getRegion(); // Do not show local variables belonging to a function other than // where the error is reported. if (auto MR = dyn_cast<StackSpaceRegion>(R->getMemorySpace())) if (MR->getStackFrame() == LeakContext->getStackFrame()) FirstBinding = R; } // AllocationNode is the last node in which the symbol was tracked. AllocationNode = N; // AllocationNodeInCurrentContext, is the last node in the current or // parent context in which the symbol was tracked. // // Note that the allocation site might be in the parent context. For example, // the case where an allocation happens in a block that captures a reference // to it and that reference is overwritten/dropped by another call to // the block. if (NContext == LeakContext || NContext->isParentOf(LeakContext)) AllocationNodeInCurrentOrParentContext = N; // Find the last init that was called on the given symbol and store the // init method's location context. if (!InitMethodContext) if (auto CEP = N->getLocation().getAs<CallEnter>()) { const Stmt *CE = CEP->getCallExpr(); if (const auto *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) { const Stmt *RecExpr = ME->getInstanceReceiver(); if (RecExpr) { SVal RecV = St->getSVal(RecExpr, NContext); if (ME->getMethodFamily() == OMF_init && RecV.getAsSymbol() == Sym) InitMethodContext = CEP->getCalleeContext(); } } } N = N->getFirstPred(); } // If we are reporting a leak of the object that was allocated with alloc, // mark its init method as interesting. const LocationContext *InterestingMethodContext = nullptr; if (InitMethodContext) { const ProgramPoint AllocPP = AllocationNode->getLocation(); if (Optional<StmtPoint> SP = AllocPP.getAs<StmtPoint>()) if (const ObjCMessageExpr *ME = SP->getStmtAs<ObjCMessageExpr>()) if (ME->getMethodFamily() == OMF_alloc) InterestingMethodContext = InitMethodContext; } // If allocation happened in a function different from the leak node context, // do not report the binding. assert(N && "Could not find allocation node"); if (AllocationNodeInCurrentOrParentContext && AllocationNodeInCurrentOrParentContext->getLocationContext() != LeakContext) FirstBinding = nullptr; return AllocationInfo(AllocationNodeInCurrentOrParentContext, FirstBinding, InterestingMethodContext); }