llvm/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp

//===-- StreamChecker.cpp -----------------------------------------*- C++ -*--//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines checkers that model and check stream handling functions.
//
//===----------------------------------------------------------------------===//

#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;

//===----------------------------------------------------------------------===//
// Definition of state data structures.
//===----------------------------------------------------------------------===//

namespace {

struct FnDescription;

/// State of the stream error flags.
/// Sometimes it is not known to the checker what error flags are set.
/// This is indicated by setting more than one flag to true.
/// This is an optimization to avoid state splits.
/// A stream can either be in FEOF or FERROR but not both at the same time.
/// Multiple flags are set to handle the corresponding states together.
struct StreamErrorState {};

const StreamErrorState ErrorNone{};
const StreamErrorState ErrorFEof{};
const StreamErrorState ErrorFError{};

/// Full state information about a stream pointer.
struct StreamState {};

} // namespace

// This map holds the state of a stream.
// The stream is identified with a SymbolRef that is created when a stream
// opening function is modeled by the checker.
REGISTER_MAP_WITH_PROGRAMSTATE()

//===----------------------------------------------------------------------===//
// StreamChecker class and utility functions.
//===----------------------------------------------------------------------===//

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 {}

/// Get the value of the stream argument out of the passed call event.
/// The call should contain a function that is described by Desc.
SVal getStreamArg(const FnDescription *Desc, const CallEvent &Call) {}

/// Create a conjured symbol return value for a call expression.
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 {};

} // end anonymous namespace

//===----------------------------------------------------------------------===//
// Definition of NoStreamStateChangeVisitor.
//===----------------------------------------------------------------------===//

namespace {
class NoStreamStateChangeVisitor final : public NoOwnershipChangeVisitor {};

} // end anonymous namespace

const ExplodedNode *StreamChecker::getAcquisitionSite(const ExplodedNode *N,
                                                      SymbolRef StreamSym,
                                                      CheckerContext &C) {}

static std::optional<int64_t> getKnownValue(ProgramStateRef State, SVal V) {}

/// Invalidate only the requested elements instead of the whole buffer.
/// This is basically a refinement of the more generic 'escapeArgs' or
/// the plain old 'invalidateRegions'.
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) {}

//===----------------------------------------------------------------------===//
// Methods of StreamChecker.
//===----------------------------------------------------------------------===//

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 {};
} // namespace

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 {}

//===----------------------------------------------------------------------===//
// Checker registration.
//===----------------------------------------------------------------------===//

void ento::registerStreamChecker(CheckerManager &Mgr) {}

bool ento::shouldRegisterStreamChecker(const CheckerManager &Mgr) {}

void ento::registerStreamTesterChecker(CheckerManager &Mgr) {}

bool ento::shouldRegisterStreamTesterChecker(const CheckerManager &Mgr) {}