/// Given the address expression, retrieve the value it's pointing to. Assume /// that value is itself an address, and return the corresponding symbol. static SymbolRef getAsPointeeSymbol(const Expr *Expr, CheckerContext &C) { ProgramStateRef State = C.getState(); SVal ArgV = State->getSVal(Expr, C.getLocationContext()); if (Optional<loc::MemRegionVal> X = ArgV.getAs<loc::MemRegionVal>()) { StoreManager& SM = C.getStoreManager(); SymbolRef sym = SM.getBinding(State->getStore(), *X).getAsLocSymbol(); if (sym) return sym; } return 0; }
bool IntegerOverflowChecker::hasGlobalVariablesOrMembers(const Stmt *S, CheckerContext &C) const { if (S == NULL || S->getStmtClass() == Stmt::IntegerLiteralClass) return false; ProgramStateRef State = C.getState(); const LocationContext *LCtx = C.getLocationContext(); if ((S->getStmtClass() != Stmt::ImplicitCastExprClass) && isInWhiteList(S, State, LCtx)) return true; if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(S)) { if (MExpr->getMemberDecl()->isFunctionOrFunctionTemplate()) return hasGlobalVariablesOrMembers(MExpr->getMemberDecl()->getBody(), C); // We found member usage! return true; } if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) if (isa<DeclRefExpr>(ICE->getSubExpr()) && isInWhiteList(C.getSVal(ICE), State)) return true; if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) if (const VarDecl *VarD = dyn_cast<VarDecl>(DRE->getDecl())) { Loc VLoc = C.getStoreManager().getLValueVar(VarD, LCtx); SVal VVal = C.getStoreManager().getBinding(State->getStore(), VLoc); if (isInWhiteList(VVal, State)) return true; } // We will not surrender! for (auto I = S->child_begin(); I != S->child_end(); I++) if (hasGlobalVariablesOrMembers(*I, C)) return true; return false; }
void StackAddrEscapeChecker::checkEndPath(CheckerContext &Ctx) const { ProgramStateRef state = Ctx.getState(); // Iterate over all bindings to global variables and see if it contains // a memory region in the stack space. class CallBack : public StoreManager::BindingsHandler { private: CheckerContext &Ctx; const StackFrameContext *CurSFC; public: SmallVector<std::pair<const MemRegion*, const MemRegion*>, 10> V; CallBack(CheckerContext &CC) : Ctx(CC), CurSFC(CC.getLocationContext()->getCurrentStackFrame()) {} bool HandleBinding(StoreManager &SMgr, Store store, const MemRegion *region, SVal val) { if (!isa<GlobalsSpaceRegion>(region->getMemorySpace())) return true; const MemRegion *vR = val.getAsRegion(); if (!vR) return true; // Under automated retain release, it is okay to assign a block // directly to a global variable. if (Ctx.getASTContext().getLangOpts().ObjCAutoRefCount && isa<BlockDataRegion>(vR)) return true; if (const StackSpaceRegion *SSR = dyn_cast<StackSpaceRegion>(vR->getMemorySpace())) { // If the global variable holds a location in the current stack frame, // record the binding to emit a warning. if (SSR->getStackFrame() == CurSFC) V.push_back(std::make_pair(region, vR)); } return true; } }; CallBack cb(Ctx); state->getStateManager().getStoreManager().iterBindings(state->getStore(),cb); if (cb.V.empty()) return; // Generate an error node. ExplodedNode *N = Ctx.addTransition(state); if (!N) return; if (!BT_stackleak) BT_stackleak.reset( new BuiltinBug("Stack address stored into global variable", "Stack address was saved into a global variable. " "This is dangerous because the address will become " "invalid after returning from the function")); for (unsigned i = 0, e = cb.V.size(); i != e; ++i) { // Generate a report for this bug. SmallString<512> buf; llvm::raw_svector_ostream os(buf); SourceRange range = GenName(os, cb.V[i].second, Ctx.getSourceManager()); os << " is still referred to by the global variable '"; const VarRegion *VR = cast<VarRegion>(cb.V[i].first->getBaseRegion()); os << *VR->getDecl() << "' upon returning to the caller. This will be a dangling reference"; BugReport *report = new BugReport(*BT_stackleak, os.str(), N); if (range.isValid()) report->addRange(range); Ctx.EmitReport(report); } }
void StackAddrEscapeChecker::checkEndFunction(CheckerContext &Ctx) const { if (!ChecksEnabled[CK_StackAddrEscapeChecker]) return; ProgramStateRef State = Ctx.getState(); // Iterate over all bindings to global variables and see if it contains // a memory region in the stack space. class CallBack : public StoreManager::BindingsHandler { private: CheckerContext &Ctx; const StackFrameContext *CurSFC; public: SmallVector<std::pair<const MemRegion *, const MemRegion *>, 10> V; CallBack(CheckerContext &CC) : Ctx(CC), CurSFC(CC.getLocationContext()->getCurrentStackFrame()) {} bool HandleBinding(StoreManager &SMgr, Store S, const MemRegion *Region, SVal Val) override { if (!isa<GlobalsSpaceRegion>(Region->getMemorySpace())) return true; const MemRegion *VR = Val.getAsRegion(); if (VR && isa<StackSpaceRegion>(VR->getMemorySpace()) && !isArcManagedBlock(VR, Ctx) && !isNotInCurrentFrame(VR, Ctx)) V.emplace_back(Region, VR); return true; } }; CallBack Cb(Ctx); State->getStateManager().getStoreManager().iterBindings(State->getStore(), Cb); if (Cb.V.empty()) return; // Generate an error node. ExplodedNode *N = Ctx.generateNonFatalErrorNode(State); if (!N) return; if (!BT_stackleak) BT_stackleak = llvm::make_unique<BuiltinBug>( this, "Stack address stored into global variable", "Stack address was saved into a global variable. " "This is dangerous because the address will become " "invalid after returning from the function"); for (const auto &P : Cb.V) { // Generate a report for this bug. SmallString<128> Buf; llvm::raw_svector_ostream Out(Buf); SourceRange Range = genName(Out, P.second, Ctx.getASTContext()); Out << " is still referred to by the "; if (isa<StaticGlobalSpaceRegion>(P.first->getMemorySpace())) Out << "static"; else Out << "global"; Out << " variable '"; const VarRegion *VR = cast<VarRegion>(P.first->getBaseRegion()); Out << *VR->getDecl() << "' upon returning to the caller. This will be a dangling reference"; auto Report = llvm::make_unique<BugReport>(*BT_stackleak, Out.str(), N); if (Range.isValid()) Report->addRange(Range); Ctx.emitReport(std::move(Report)); } }
StoreRef StoreManager::enterStackFrame(ProgramStateRef state, const LocationContext *callerCtx, const StackFrameContext *calleeCtx) { return StoreRef(state->getStore(), *this); }