30 #include "llvm/ADT/STLExtras.h"
32 using namespace clang;
39 const char *ErrnoVarName =
"errno";
42 const char *ErrnoLocationFuncNames[] = {
"__errno_location",
"___errno",
43 "__errno",
"_errno",
"__error"};
46 :
public Checker<check::ASTDecl<TranslationUnitDecl>, check::BeginFunction,
47 check::LiveSymbols, eval::Call> {
50 BugReporter &BR)
const;
51 void checkBeginFunction(CheckerContext &C)
const;
53 bool evalCall(
const CallEvent &Call, CheckerContext &C)
const;
56 mutable const Decl *ErrnoDecl =
nullptr;
60 CallDescriptionSet ErrnoLocationCalls{{
"__errno_location", 0, 0},
79 auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II);
80 auto Found = llvm::find_if(LookupRes, [&ACtx](
const Decl *D) {
81 if (
auto *VD = dyn_cast<VarDecl>(D))
82 return ACtx.getSourceManager().isInSystemHeader(VD->getLocation()) &&
83 VD->hasExternalStorage() &&
84 VD->getType().getCanonicalType() == ACtx.IntTy;
87 if (Found == LookupRes.end())
90 return cast<VarDecl>(*Found);
98 for (StringRef ErrnoName : ErrnoLocationFuncNames) {
103 auto Found = llvm::find_if(LookupRes, [&ACtx](
const Decl *D) {
104 if (
auto *FD = dyn_cast<FunctionDecl>(D))
106 FD->isExternC() && FD->getNumParams() == 0 &&
107 FD->getReturnType().getCanonicalType() ==
111 if (Found == LookupRes.end())
114 return cast<FunctionDecl>(*Found);
118 AnalysisManager &Mgr, BugReporter &BR)
const {
130 void ErrnoModeling::checkBeginFunction(CheckerContext &C)
const {
137 if (
const auto *ErrnoVar = dyn_cast_or_null<VarDecl>(ErrnoDecl)) {
142 const MemRegion *ErrnoR =
143 State->getRegion(ErrnoVar,
C.getLocationContext());
144 assert(ErrnoR &&
"Memory region should exist for the 'errno' variable.");
149 }
else if (ErrnoDecl) {
150 assert(isa<FunctionDecl>(ErrnoDecl) &&
"Invalid errno location function.");
156 SValBuilder &SVB =
C.getSValBuilder();
157 MemRegionManager &RMgr =
C.getStateManager().getRegionManager();
159 const MemSpaceRegion *GlobalSystemSpace =
160 RMgr.getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind);
164 const SymbolConjured *Sym = SVB.conjureSymbol(
165 nullptr,
C.getLocationContext(),
170 const MemRegion *ErrnoR = RMgr.getElementRegion(
171 ACtx.
IntTy, SVB.makeZeroArrayIndex(),
172 RMgr.getSymbolicRegion(Sym, GlobalSystemSpace),
C.getASTContext());
180 bool ErrnoModeling::evalCall(
const CallEvent &Call, CheckerContext &C)
const {
183 if (ErrnoLocationCalls.contains(Call)) {
186 const MemRegion *ErrnoR =
State->get<ErrnoRegion>();
191 loc::MemRegionVal{ErrnoR});
200 SymbolReaper &SR)
const {
202 if (
const auto *ErrnoR =
State->get<ErrnoRegion>())
208 namespace errno_modeling {
214 QualType IntTy =
State->getAnalysisManager().getASTContext().IntTy;
215 return State->getSVal(ErrnoR, IntTy);
227 return State->set<ErrnoState>(EState);
237 C.getSValBuilder().makeIntVal(
Value, C.getASTContext().IntTy),
238 C.getLocationContext());
239 return State->set<ErrnoState>(EState);
250 return State->set<ErrnoState>(EState);
254 return State->get<ErrnoState>();
258 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
260 return II->getName() == ErrnoVarName;
261 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(D))
263 return llvm::is_contained(ErrnoLocationFuncNames, II->getName());
271 BR.markNotInteresting(ErrnoR);
282 void ento::registerErrnoModeling(CheckerManager &mgr) {
283 mgr.registerChecker<ErrnoModeling>();
286 bool ento::shouldRegisterErrnoModeling(
const CheckerManager &mgr) {