#include "InterCheckerAPI.h"
#include "clang/AST/OperationKinds.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/CharInfo.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.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/DynamicExtent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include <functional>
#include <optional>
usingnamespaceclang;
usingnamespaceento;
usingnamespacestd::placeholders;
namespace {
struct AnyArgExpr { … };
struct SourceArgExpr : AnyArgExpr { … };
struct DestinationArgExpr : AnyArgExpr { … };
struct SizeArgExpr : AnyArgExpr { … };
ErrorMessage;
enum class AccessKind { … };
static ErrorMessage createOutOfBoundErrorMsg(StringRef FunctionDescription,
AccessKind Access) { … }
enum class ConcatFnKind { … };
enum class CharKind { … };
constexpr CharKind CK_Regular = …;
constexpr CharKind CK_Wide = …;
static QualType getCharPtrType(ASTContext &Ctx, CharKind CK) { … }
class CStringChecker : public Checker< eval::Call,
check::PreStmt<DeclStmt>,
check::LiveSymbols,
check::DeadSymbols,
check::RegionChanges
> { … };
}
REGISTER_MAP_WITH_PROGRAMSTATE(…) …
std::pair<ProgramStateRef, ProgramStateRef>
CStringChecker::assumeZero(CheckerContext &C, ProgramStateRef State, SVal V,
QualType Ty) { … }
ProgramStateRef CStringChecker::checkNonNull(CheckerContext &C,
ProgramStateRef State,
AnyArgExpr Arg, SVal l) const { … }
static std::optional<NonLoc> getIndex(ProgramStateRef State,
const ElementRegion *ER, CharKind CK) { … }
static void printIdxWithOrdinalSuffix(llvm::raw_ostream &Os, unsigned Idx) { … }
ProgramStateRef CStringChecker::checkInit(CheckerContext &C,
ProgramStateRef State,
AnyArgExpr Buffer, SVal Element,
SVal Size) const { … }
ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
ProgramStateRef state,
AnyArgExpr Buffer, SVal Element,
AccessKind Access,
CharKind CK) const { … }
ProgramStateRef
CStringChecker::CheckBufferAccess(CheckerContext &C, ProgramStateRef State,
AnyArgExpr Buffer, SizeArgExpr Size,
AccessKind Access, CharKind CK) const { … }
ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,
ProgramStateRef state,
SizeArgExpr Size, AnyArgExpr First,
AnyArgExpr Second,
CharKind CK) const { … }
void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state,
const Stmt *First, const Stmt *Second) const { … }
void CStringChecker::emitNullArgBug(CheckerContext &C, ProgramStateRef State,
const Stmt *S, StringRef WarningMsg) const { … }
void CStringChecker::emitUninitializedReadBug(CheckerContext &C,
ProgramStateRef State,
const Expr *E, const MemRegion *R,
StringRef Msg) const { … }
void CStringChecker::emitOutOfBoundsBug(CheckerContext &C,
ProgramStateRef State, const Stmt *S,
StringRef WarningMsg) const { … }
void CStringChecker::emitNotCStringBug(CheckerContext &C, ProgramStateRef State,
const Stmt *S,
StringRef WarningMsg) const { … }
void CStringChecker::emitAdditionOverflowBug(CheckerContext &C,
ProgramStateRef State) const { … }
ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
ProgramStateRef state,
NonLoc left,
NonLoc right) const { … }
ProgramStateRef CStringChecker::setCStringLength(ProgramStateRef state,
const MemRegion *MR,
SVal strLength) { … }
SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
ProgramStateRef &state,
const Expr *Ex,
const MemRegion *MR,
bool hypothetical) { … }
SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
const Expr *Ex, SVal Buf,
bool hypothetical) const { … }
const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C,
ProgramStateRef &state, const Expr *expr, SVal val) const { … }
bool CStringChecker::isFirstBufInBound(CheckerContext &C, ProgramStateRef State,
SVal BufVal, QualType BufTy,
SVal LengthVal, QualType LengthTy) { … }
ProgramStateRef CStringChecker::invalidateDestinationBufferBySize(
CheckerContext &C, ProgramStateRef S, const Expr *BufE, SVal BufV,
SVal SizeV, QualType SizeTy) { … }
ProgramStateRef
CStringChecker::invalidateDestinationBufferAlwaysEscapeSuperRegion(
CheckerContext &C, ProgramStateRef S, const Expr *BufE, SVal BufV) { … }
ProgramStateRef CStringChecker::invalidateDestinationBufferNeverOverflows(
CheckerContext &C, ProgramStateRef S, const Expr *BufE, SVal BufV) { … }
ProgramStateRef CStringChecker::invalidateSourceBuffer(CheckerContext &C,
ProgramStateRef S,
const Expr *BufE,
SVal BufV) { … }
ProgramStateRef CStringChecker::invalidateBufferAux(
CheckerContext &C, ProgramStateRef State, const Expr *E, SVal V,
llvm::function_ref<bool(RegionAndSymbolInvalidationTraits &,
const MemRegion *)>
InvalidationTraitOperations) { … }
bool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
const MemRegion *MR) { … }
bool CStringChecker::memsetAux(const Expr *DstBuffer, SVal CharVal,
const Expr *Size, CheckerContext &C,
ProgramStateRef &State) { … }
void CStringChecker::evalCopyCommon(CheckerContext &C, const CallEvent &Call,
ProgramStateRef state, SizeArgExpr Size,
DestinationArgExpr Dest,
SourceArgExpr Source, bool Restricted,
bool IsMempcpy, CharKind CK) const { … }
void CStringChecker::evalMemcpy(CheckerContext &C, const CallEvent &Call,
CharKind CK) const { … }
void CStringChecker::evalMempcpy(CheckerContext &C, const CallEvent &Call,
CharKind CK) const { … }
void CStringChecker::evalMemmove(CheckerContext &C, const CallEvent &Call,
CharKind CK) const { … }
void CStringChecker::evalBcopy(CheckerContext &C, const CallEvent &Call) const { … }
void CStringChecker::evalMemcmp(CheckerContext &C, const CallEvent &Call,
CharKind CK) const { … }
void CStringChecker::evalstrLength(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalstrnLength(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalstrLengthCommon(CheckerContext &C,
const CallEvent &Call,
bool IsStrnlen) const { … }
void CStringChecker::evalStrcpy(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStrncpy(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStpcpy(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStrlcpy(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStrcat(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStrncat(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStrlcat(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallEvent &Call,
bool ReturnEnd, bool IsBounded,
ConcatFnKind appendK,
bool returnPtr) const { … }
void CStringChecker::evalStrcmp(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStrncmp(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStrcasecmp(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStrncasecmp(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallEvent &Call,
bool IsBounded, bool IgnoreCase) const { … }
void CStringChecker::evalStrsep(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStdCopy(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStdCopyBackward(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalStdCopyCommon(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalMemset(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalBzero(CheckerContext &C, const CallEvent &Call) const { … }
void CStringChecker::evalSprintf(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalSnprintf(CheckerContext &C,
const CallEvent &Call) const { … }
void CStringChecker::evalSprintfCommon(CheckerContext &C, const CallEvent &Call,
bool IsBounded) const { … }
CStringChecker::FnCheck CStringChecker::identifyCall(const CallEvent &Call,
CheckerContext &C) const { … }
bool CStringChecker::evalCall(const CallEvent &Call, CheckerContext &C) const { … }
void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { … }
ProgramStateRef
CStringChecker::checkRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) const { … }
void CStringChecker::checkLiveSymbols(ProgramStateRef state,
SymbolReaper &SR) const { … }
void CStringChecker::checkDeadSymbols(SymbolReaper &SR,
CheckerContext &C) const { … }
void ento::registerCStringModeling(CheckerManager &Mgr) { … }
bool ento::shouldRegisterCStringModeling(const CheckerManager &mgr) { … }
#define REGISTER_CHECKER(name) …
REGISTER_CHECKER(CStringNullArg)
REGISTER_CHECKER(CStringOutOfBounds)
REGISTER_CHECKER(CStringBufferOverlap)
REGISTER_CHECKER(CStringNotNullTerm)
REGISTER_CHECKER(CStringUninitializedRead)