//= CStringChecker.h - Checks calls to C string functions ----------*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This defines CStringChecker, which is an assortment of checks on calls
// to functions in <string.h>.
//
//===----------------------------------------------------------------------===//
#include "GRExprEngineExperimentalChecks.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
#include "clang/Checker/PathSensitive/GRStateTrait.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
namespace {
class CStringChecker : public CheckerVisitor<CStringChecker> {
BugType *BT_Null, *BT_Bounds, *BT_Overlap, *BT_NotCString;
public:
CStringChecker()
: BT_Null(0), BT_Bounds(0), BT_Overlap(0), BT_NotCString(0) {}
static void *getTag() { static int tag; return &tag; }
bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
void MarkLiveSymbols(const GRState *state, SymbolReaper &SR);
void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SR);
bool WantsRegionChangeUpdate(const GRState *state);
const GRState *EvalRegionChanges(const GRState *state,
const MemRegion * const *Begin,
const MemRegion * const *End,
bool*);
typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *);
void EvalMemcpy(CheckerContext &C, const CallExpr *CE);
void EvalMemmove(CheckerContext &C, const CallExpr *CE);
void EvalBcopy(CheckerContext &C, const CallExpr *CE);
void EvalCopyCommon(CheckerContext &C, const GRState *state,
const Expr *Size, const Expr *Source, const Expr *Dest,
bool Restricted = false);
void EvalMemcmp(CheckerContext &C, const CallExpr *CE);
void EvalStrlen(CheckerContext &C, const CallExpr *CE);
// Utility methods
std::pair<const GRState*, const GRState*>
AssumeZero(CheckerContext &C, const GRState *state, SVal V, QualType Ty);
SVal GetCStringLengthForRegion(CheckerContext &C, const GRState *&state,
const Expr *Ex, const MemRegion *MR);
SVal GetCStringLength(CheckerContext &C, const GRState *&state,
const Expr *Ex, SVal Buf);
bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
const MemRegion *MR);
// Re-usable checks
const GRState *CheckNonNull(CheckerContext &C, const GRState *state,
const Expr *S, SVal l);
const GRState *CheckLocation(CheckerContext &C, const GRState *state,
const Expr *S, SVal l);
const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state,
const Expr *Size,
const Expr *FirstBuf,
const Expr *SecondBuf = NULL);
const GRState *CheckOverlap(CheckerContext &C, const GRState *state,
const Expr *Size, const Expr *First,
const Expr *Second);
void EmitOverlapBug(CheckerContext &C, const GRState *state,
const Stmt *First, const Stmt *Second);
};
class CStringLength {
public:
typedef llvm::ImmutableMap<const MemRegion *, SVal> EntryMap;
};
} //end anonymous namespace
namespace clang {
template <>
struct GRStateTrait<CStringLength>
: public GRStatePartialTrait<CStringLength::EntryMap> {
static void *GDMIndex() { return CStringChecker::getTag(); }
};
}
void clang::RegisterCStringChecker(GRExprEngine &Eng) {
Eng.registerCheck(new CStringChecker());
}
//===----------------------------------------------------------------------===//
// Individual checks and utility methods.
//===----------------------------------------------------------------------===//
std::pair<const GRState*, const GRState*>
CStringChecker::AssumeZero(CheckerContext &C, const GRState *state, SVal V,
QualType Ty) {
DefinedSVal *Val = dyn_cast<DefinedSVal>(&V);
if (!Val)
return std::pair<const GRState*, const GRState *>(state, state);
ValueManager &ValMgr = C.getValueManager();
SValuator &SV = ValMgr.getSValuator();
DefinedOrUnknownSVal Zero = ValMgr.makeZeroVal(Ty);
DefinedOrUnknownSVal ValIsZero