23 using namespace clang;
29 enum Kind { Opened, Closed, OpenFailed, Escaped } K;
32 StreamState(
Kind k,
const Stmt *s) : K(k),
S(s) {}
34 bool isOpened()
const {
return K == Opened; }
35 bool isClosed()
const {
return K == Closed; }
40 return K == X.K &&
S == X.S;
43 static StreamState getOpened(
const Stmt *s) {
return StreamState(Opened, s); }
44 static StreamState getClosed(
const Stmt *s) {
return StreamState(Closed, s); }
45 static StreamState getOpenFailed(
const Stmt *s) {
46 return StreamState(OpenFailed, s);
48 static StreamState getEscaped(
const Stmt *s) {
49 return StreamState(Escaped, s);
52 void Profile(llvm::FoldingSetNodeID &
ID)
const {
58 class StreamChecker :
public Checker<eval::Call,
59 check::DeadSymbols > {
60 mutable IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread,
62 *II_fseek, *II_ftell, *II_rewind, *II_fgetpos, *II_fsetpos,
63 *II_clearerr, *II_feof, *II_ferror, *II_fileno;
64 mutable std::unique_ptr<BuiltinBug> BT_nullfp, BT_illegalwhence,
65 BT_doubleclose, BT_ResourceLeak;
69 : II_fopen(nullptr), II_tmpfile(nullptr), II_fclose(nullptr),
70 II_fread(nullptr), II_fwrite(nullptr), II_fseek(nullptr),
71 II_ftell(nullptr), II_rewind(nullptr), II_fgetpos(nullptr),
72 II_fsetpos(nullptr), II_clearerr(nullptr), II_feof(nullptr),
73 II_ferror(nullptr), II_fileno(nullptr) {}
109 if (!FD || FD->
getKind() != Decl::Function)
134 II_clearerr = &Ctx.
Idents.
get(
"clearerr");
216 .castAs<DefinedSVal>();
223 std::tie(stateNotNull, stateNull) = CM.
assumeDual(state, RetVal);
228 stateNotNull->set<StreamMap>(Sym,StreamState::getOpened(CE));
230 stateNull->set<StreamMap>(Sym, StreamState::getOpenFailed(CE));
259 if (!(state = CheckNullStream(state->getSVal(CE->
getArg(0),
269 int64_t x = CI->getValue().getSExtValue();
270 if (x >= 0 && x <= 2)
274 if (!BT_illegalwhence)
275 BT_illegalwhence.reset(
276 new BuiltinBug(
this,
"Illegal whence argument",
277 "The whence argument to fseek() should be "
278 "SEEK_SET, SEEK_END, or SEEK_CUR."));
280 *BT_illegalwhence, BT_illegalwhence->getDescription(), N));
348 std::tie(stateNotNull, stateNull) = CM.
assumeDual(state, *DV);
350 if (!stateNotNull && stateNull) {
353 BT_nullfp.reset(
new BuiltinBug(
this,
"NULL stream pointer",
354 "Stream pointer might be NULL."));
356 *BT_nullfp, BT_nullfp->getDescription(), N));
371 const StreamState *SS = state->get<StreamMap>(Sym);
379 if (SS->isClosed()) {
384 this,
"Double fclose",
"Try to close a file Descriptor already"
385 " closed. Cause undefined behaviour."));
387 *BT_doubleclose, BT_doubleclose->getDescription(), N));
393 return state->set<StreamMap>(Sym, StreamState::getClosed(CE));
396 void StreamChecker::checkDeadSymbols(
SymbolReaper &SymReaper,
403 const StreamState *SS = state->get<StreamMap>(Sym);
407 if (SS->isOpened()) {
410 if (!BT_ResourceLeak)
412 this,
"Resource Leak",
413 "Opened File never closed. Potential Resource leak."));
415 *BT_ResourceLeak, BT_ResourceLeak->getDescription(), N));
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
bool operator==(CanQual< T > x, CanQual< U > y)
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
Stmt - This represents one statement.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
Value representing integer constant.
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
One of these records is kept for each identifier that is lexed.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
dead_iterator dead_begin() const
detail::InMemoryDirectory::const_iterator I
const LocationContext * getLocationContext() const
ProgramStatePair assumeDual(ProgramStateRef State, DefinedSVal Cond)
Returns a pair of states (StTrue, StFalse) where the given condition is assumed to be true or false...
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
const ProgramStateRef & getState() const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
SymbolSetTy::const_iterator dead_iterator
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
ConstraintManager & getConstraintManager()
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
CHECKER * registerChecker()
Used to register checkers.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
dead_iterator dead_end() const
A class responsible for cleaning up unused symbols.
detail::InMemoryDirectory::const_iterator E
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
SValBuilder & getSValBuilder()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
const LocationContext * getLocationContext() const