#include "NoOwnershipChangeVisitor.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/Sequence.h"
#include <functional>
#include <optional>
usingnamespaceclang;
usingnamespaceento;
usingnamespacestd::placeholders;
namespace {
struct FnDescription;
struct StreamErrorState { … };
const StreamErrorState ErrorNone{ … };
const StreamErrorState ErrorFEof{ … };
const StreamErrorState ErrorFError{ … };
struct StreamState { … };
}
REGISTER_MAP_WITH_PROGRAMSTATE(…)
namespace {
class StreamChecker;
FnCheck;
ArgNoTy;
static const ArgNoTy ArgNone = …;
const char *FeofNote = …;
const char *FerrorNote = …;
struct FnDescription { … };
LLVM_DUMP_METHOD void StreamState::dumpToStream(llvm::raw_ostream &os) const { … }
SVal getStreamArg(const FnDescription *Desc, const CallEvent &Call) { … }
DefinedSVal makeRetVal(CheckerContext &C, const CallExpr *CE) { … }
ProgramStateRef bindAndAssumeTrue(ProgramStateRef State, CheckerContext &C,
const CallExpr *CE) { … }
ProgramStateRef bindInt(uint64_t Value, ProgramStateRef State,
CheckerContext &C, const CallExpr *CE) { … }
inline void assertStreamStateOpened(const StreamState *SS) { … }
class StreamChecker : public Checker<check::PreCall, eval::Call,
check::DeadSymbols, check::PointerEscape,
check::ASTDecl<TranslationUnitDecl>> { … };
struct StreamOperationEvaluator { … };
}
namespace {
class NoStreamStateChangeVisitor final : public NoOwnershipChangeVisitor { … };
}
const ExplodedNode *StreamChecker::getAcquisitionSite(const ExplodedNode *N,
SymbolRef StreamSym,
CheckerContext &C) { … }
static std::optional<int64_t> getKnownValue(ProgramStateRef State, SVal V) { … }
static ProgramStateRef
escapeByStartIndexAndCount(ProgramStateRef State, const CallEvent &Call,
unsigned BlockCount, const SubRegion *Buffer,
QualType ElemType, int64_t StartIndex,
int64_t ElementCount) { … }
static ProgramStateRef escapeArgs(ProgramStateRef State, CheckerContext &C,
const CallEvent &Call,
ArrayRef<unsigned int> EscapingArgs) { … }
void StreamChecker::checkPreCall(const CallEvent &Call,
CheckerContext &C) const { … }
bool StreamChecker::evalCall(const CallEvent &Call, CheckerContext &C) const { … }
ProgramStateRef StreamChecker::assumeNoAliasingWithStdStreams(
ProgramStateRef State, DefinedSVal RetVal, CheckerContext &C) const { … }
void StreamChecker::evalFopen(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::preFreopen(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalFreopen(const FnDescription *Desc,
const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalFclose(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::preRead(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::preWrite(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
static QualType getPointeeType(const MemRegion *R) { … }
static std::optional<NonLoc> getStartIndex(SValBuilder &SVB,
const MemRegion *R) { … }
static ProgramStateRef
tryToInvalidateFReadBufferByElements(ProgramStateRef State, CheckerContext &C,
const CallEvent &Call, NonLoc SizeVal,
NonLoc NMembVal) { … }
void StreamChecker::evalFreadFwrite(const FnDescription *Desc,
const CallEvent &Call, CheckerContext &C,
bool IsFread) const { … }
void StreamChecker::evalFgetx(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C, bool SingleChar) const { … }
void StreamChecker::evalFputx(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C, bool IsSingleChar) const { … }
void StreamChecker::evalFprintf(const FnDescription *Desc,
const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalFscanf(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalUngetc(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalGetdelim(const FnDescription *Desc,
const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::preFseek(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalFseek(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalFgetpos(const FnDescription *Desc,
const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalFsetpos(const FnDescription *Desc,
const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalFtell(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalRewind(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::preFflush(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalFflush(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalClearerr(const FnDescription *Desc,
const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalFeofFerror(const FnDescription *Desc,
const CallEvent &Call, CheckerContext &C,
const StreamErrorState &ErrorKind) const { … }
void StreamChecker::evalFileno(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::preDefault(const FnDescription *Desc, const CallEvent &Call,
CheckerContext &C) const { … }
void StreamChecker::evalSetFeofFerror(const FnDescription *Desc,
const CallEvent &Call, CheckerContext &C,
const StreamErrorState &ErrorKind,
bool Indeterminate) const { … }
ProgramStateRef
StreamChecker::ensureStreamNonNull(SVal StreamVal, const Expr *StreamE,
CheckerContext &C,
ProgramStateRef State) const { … }
namespace {
class StreamClosedVisitor final : public BugReporterVisitor { … };
}
ProgramStateRef StreamChecker::ensureStreamOpened(SVal StreamVal,
CheckerContext &C,
ProgramStateRef State) const { … }
ProgramStateRef StreamChecker::ensureNoFilePositionIndeterminate(
SVal StreamVal, CheckerContext &C, ProgramStateRef State) const { … }
ProgramStateRef
StreamChecker::ensureFseekWhenceCorrect(SVal WhenceVal, CheckerContext &C,
ProgramStateRef State) const { … }
void StreamChecker::reportFEofWarning(SymbolRef StreamSym, CheckerContext &C,
ProgramStateRef State) const { … }
ExplodedNode *
StreamChecker::reportLeaks(const SmallVector<SymbolRef, 2> &LeakedSyms,
CheckerContext &C, ExplodedNode *Pred) const { … }
void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
CheckerContext &C) const { … }
ProgramStateRef StreamChecker::checkPointerEscape(
ProgramStateRef State, const InvalidatedSymbols &Escaped,
const CallEvent *Call, PointerEscapeKind Kind) const { … }
static const VarDecl *
getGlobalStreamPointerByName(const TranslationUnitDecl *TU, StringRef VarName) { … }
void StreamChecker::checkASTDecl(const TranslationUnitDecl *TU,
AnalysisManager &Mgr, BugReporter &) const { … }
void ento::registerStreamChecker(CheckerManager &Mgr) { … }
bool ento::shouldRegisterStreamChecker(const CheckerManager &Mgr) { … }
void ento::registerStreamTesterChecker(CheckerManager &Mgr) { … }
bool ento::shouldRegisterStreamTesterChecker(const CheckerManager &Mgr) { … }