29#include "llvm/ADT/STLExtras.h"
39const char *ErrnoVarName =
"errno";
44 {CDM::CLibrary, {
"__errno_location"}, 0, 0},
45 {CDM::CLibrary, {
"___errno"}, 0, 0},
46 {CDM::CLibrary, {
"__errno"}, 0, 0},
47 {CDM::CLibrary, {
"_errno"}, 0, 0},
48 {CDM::CLibrary, {
"__error"}, 0, 0}};
51 :
public Checker<check::ASTDecl<TranslationUnitDecl>, check::BeginFunction,
52 check::LiveSymbols, eval::Call> {
54 void checkASTDecl(
const TranslationUnitDecl *D, AnalysisManager &Mgr,
55 BugReporter &BR)
const;
56 void checkBeginFunction(CheckerContext &
C)
const;
58 bool evalCall(
const CallEvent &
Call, CheckerContext &
C)
const;
63 mutable const VarDecl *ErrnoDecl =
nullptr;
81 IdentifierInfo &II = ACtx.
Idents.
get(ErrnoVarName);
83 auto Found = llvm::find_if(LookupRes, [&ACtx](
const Decl *D) {
84 if (
auto *VD = dyn_cast<VarDecl>(D))
86 VD->hasExternalStorage() &&
87 VD->getType().getCanonicalType() == ACtx.
IntTy;
90 if (
Found != LookupRes.end())
94void ErrnoModeling::checkBeginFunction(CheckerContext &
C)
const {
98 ASTContext &ACtx =
C.getASTContext();
101 const MemRegion *ErrnoR =
nullptr;
106 ErrnoR = State->getRegion(ErrnoDecl,
C.getLocationContext());
107 assert(ErrnoR &&
"Memory region should exist for the 'errno' variable.");
113 SValBuilder &SVB =
C.getSValBuilder();
114 MemRegionManager &RMgr =
C.getStateManager().getRegionManager();
116 const MemSpaceRegion *GlobalSystemSpace =
125 C.getCFGElementRef(),
C.getLocationContext(),
135 State = State->set<ErrnoRegion>(ErrnoR);
138 C.addTransition(State);
141bool ErrnoModeling::evalCall(
const CallEvent &
Call, CheckerContext &
C)
const {
147 const MemRegion *ErrnoR = State->get<ErrnoRegion>();
151 State = State->BindExpr(
Call.getOriginExpr(),
C.getLocationContext(),
152 loc::MemRegionVal{ErrnoR});
153 C.addTransition(State);
161 SymbolReaper &SR)
const {
163 if (
const auto *ErrnoR = State->get<ErrnoRegion>())
172 const MemRegion *ErrnoR = State->get<ErrnoRegion>();
175 QualType IntTy = State->getAnalysisManager().getASTContext().IntTy;
176 return State->getSVal(ErrnoR, IntTy);
182 const MemRegion *ErrnoR = State->get<ErrnoRegion>();
188 return State->set<ErrnoState>(EState);
193 const MemRegion *ErrnoR = State->get<ErrnoRegion>();
196 State = State->bindLoc(
198 C.getSValBuilder().makeIntVal(
Value,
C.getASTContext().IntTy),
199 C.getLocationContext());
200 return State->set<ErrnoState>(EState);
204 const MemRegion *ErrnoR = State->get<ErrnoRegion>();
211 return State->get<ErrnoState>();
215 return State->set<ErrnoState>(EState);
223 return ErrnoLocationCalls.contains(CE);
249 State = State->assume(
Cond,
true);
258 const MemRegion *ErrnoR = State->get<ErrnoRegion>();
261 State = State->invalidateRegions(ErrnoR, Elem,
C.blockCount(),
262 C.getLocationContext(),
false);
272void ento::registerErrnoModeling(CheckerManager &mgr) {
276bool ento::shouldRegisterErrnoModeling(
const CheckerManager &mgr) {
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
Declares a program state trait for type Type called Name, and introduce a type named NameTy.
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
A (possibly-)qualified type.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
The top declaration context.
ASTContext & getASTContext() override
BugReporter is a utility class for generating PathDiagnostics for analysis.
An immutable set of CallDescriptions.
Represents an abstract call to a function or method along a particular path.
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
Simple checker classes that implement one frontend (i.e.
const ProgramStateRef & getState() const
const ElementRegion * getElementRegion(QualType elementType, NonLoc Idx, const SubRegion *superRegion, const ASTContext &Ctx)
getElementRegion - Retrieve the memory region associated with the associated element type,...
const GlobalsSpaceRegion * getGlobalsRegion(MemRegion::Kind K=MemRegion::GlobalInternalSpaceRegionKind, const CodeTextRegion *R=nullptr)
getGlobalsRegion - Retrieve the memory region associated with global variables.
const SymbolicRegion * getSymbolicRegion(SymbolRef Sym, const MemSpaceRegion *MemSpace=nullptr)
Retrieve or create a "symbolic" memory region.
MemRegion - The root abstract class for all memory regions.
The tag upon which the TagVisitor reacts.
const ExplodedNode * getErrorNode() const
void markNotInteresting(SymbolRef sym)
bool isInteresting(SymbolRef sym) const
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
QualType getConditionType() const
NonLoc makeZeroArrayIndex()
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
const SymbolConjured * conjureSymbol(ConstCFGElementRef Elem, const LocationContext *LCtx, QualType type, unsigned visitCount, const void *symbolTag=nullptr)
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
std::optional< Loc > getErrnoLoc(ProgramStateRef State)
Returns the location that points to the MemoryRegion where the 'errno' value is stored.
ProgramStateRef setErrnoValue(ProgramStateRef State, const LocationContext *LCtx, SVal Value, ErrnoCheckState EState)
Set value of 'errno' to any SVal, if possible.
ProgramStateRef clearErrnoState(ProgramStateRef State)
Clear state of errno (make it irrelevant).
ProgramStateRef setErrnoForStdSuccess(ProgramStateRef State, CheckerContext &C)
Set errno state for the common case when a standard function is successful.
ProgramStateRef setErrnoStdMustBeChecked(ProgramStateRef State, CheckerContext &C, ConstCFGElementRef Elem)
Set errno state for the common case when a standard function indicates failure only by errno.
ProgramStateRef setErrnoState(ProgramStateRef State, ErrnoCheckState EState)
Set the errno check state, do not modify the errno value.
const NoteTag * getErrnoNoteTag(CheckerContext &C, const std::string &Message)
Create a NoteTag that displays the message if the 'errno' memory region is marked as interesting,...
bool isErrnoLocationCall(const CallEvent &CE)
Determine if Call is a call to an internal function that returns the location of errno (in environmen...
ProgramStateRef setErrnoForStdFailure(ProgramStateRef State, CheckerContext &C, NonLoc ErrnoSym)
Set errno state for the common case when a standard function fails.
std::optional< SVal > getErrnoValue(ProgramStateRef State)
Returns the value of 'errno', if 'errno' was found in the AST.
ErrnoCheckState
Describe how reads and writes of errno are handled by the checker.
@ MustBeChecked
Value of 'errno' should be checked to find out if a previous function call has failed.
@ Irrelevant
We do not know anything about 'errno'.
@ MustNotBeChecked
Value of 'errno' is not allowed to be read, it can contain an unspecified value.
ErrnoCheckState getErrnoState(ProgramStateRef State)
Returns the errno check state, Errno_Irrelevant if 'errno' was not found (this is not the only case f...
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
The JSON file list parser is used to communicate input to InstallAPI.
CFGBlock::ConstCFGElementRef ConstCFGElementRef
U cast(CodeGen::Address addr)