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) {}
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));
257 if (!(state = CheckNullStream(C.
getSVal(CE->
getArg(0)), state, C)))
266 int64_t x = CI->getValue().getSExtValue();
267 if (x >= 0 && x <= 2)
271 if (!BT_illegalwhence)
272 BT_illegalwhence.reset(
273 new BuiltinBug(
this,
"Illegal whence argument",
274 "The whence argument to fseek() should be " 275 "SEEK_SET, SEEK_END, or SEEK_CUR."));
277 *BT_illegalwhence, BT_illegalwhence->getDescription(), N));
337 std::tie(stateNotNull, stateNull) = CM.
assumeDual(state, *DV);
339 if (!stateNotNull && stateNull) {
342 BT_nullfp.reset(
new BuiltinBug(
this,
"NULL stream pointer",
343 "Stream pointer might be NULL."));
345 *BT_nullfp, BT_nullfp->getDescription(), N));
359 const StreamState *SS = state->get<StreamMap>(Sym);
367 if (SS->isClosed()) {
372 this,
"Double fclose",
"Try to close a file Descriptor already" 373 " closed. Cause undefined behaviour."));
375 *BT_doubleclose, BT_doubleclose->getDescription(), N));
381 return state->set<StreamMap>(Sym, StreamState::getClosed(CE));
384 void StreamChecker::checkDeadSymbols(
SymbolReaper &SymReaper,
388 E = SymReaper.
dead_end(); I != E; ++I) {
391 const StreamState *SS = state->get<StreamMap>(Sym);
395 if (SS->isOpened()) {
398 if (!BT_ResourceLeak)
400 this,
"Resource Leak",
401 "Opened File never closed. Potential Resource leak."));
403 *BT_ResourceLeak, BT_ResourceLeak->getDescription(), N));
Represents 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).
constexpr XRayInstrMask Function
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...
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
IdentifierInfo * getIdentifier() const
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.
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...
CHECKER * registerChecker(AT... Args)
Used to register checkers.
ConstraintManager & getConstraintManager()
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
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...
SymbolSetTy::const_iterator dead_iterator
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