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,
400 E = SymReaper.
dead_end(); I != E; ++I) {
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));
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)
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.
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
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 ...
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
const LocationContext * getLocationContext() const
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
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.
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.
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
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...
A class responsible for cleaning up unused symbols.
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
Dataflow Directional Tag Classes.
ASTContext & getASTContext()
dead_iterator dead_begin() const
const ProgramStateRef & getState() const
dead_iterator dead_end() const
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
SValBuilder & getSValBuilder()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
const LocationContext * getLocationContext() const