20 #include "llvm/ADT/FoldingSet.h"
22 using namespace clang;
35 : ZeroSymbol(S), BlockID(B), SFC(SFC) {}
40 return BlockID == X.BlockID && SFC == X.SFC && ZeroSymbol == X.ZeroSymbol;
44 if (BlockID != X.BlockID)
45 return BlockID < X.BlockID;
48 return ZeroSymbol < X.ZeroSymbol;
51 void Profile(llvm::FoldingSetNodeID &
ID)
const {
52 ID.AddInteger(BlockID);
54 ID.AddPointer(ZeroSymbol);
66 : ZeroSymbol(ZeroSymbol), SFC(SFC), Satisfied(
false) {}
68 void Profile(llvm::FoldingSetNodeID &ID)
const override {
79 class TestAfterDivZeroChecker
80 :
public Checker<check::PreStmt<BinaryOperator>, check::BranchCondition,
82 mutable std::unique_ptr<BuiltinBug> DivZeroBug;
104 const Expr *E =
nullptr;
119 SVal S = State->getSVal(E, Succ->getLocationContext());
120 if (ZeroSymbol == S.
getAsSymbol() && SFC == Succ->getStackFrame()) {
132 L,
"Division with compared value made here");
159 bool TestAfterDivZeroChecker::hasDivZeroMap(
SVal Var,
166 return C.
getState()->contains<DivZeroMap>(ZS);
172 DivZeroBug.reset(
new BuiltinBug(
this,
"Division by zero"));
174 auto R = llvm::make_unique<BugReport>(
175 *DivZeroBug,
"Value being compared against zero has already been used "
179 R->addVisitor(llvm::make_unique<DivisionBRVisitor>(Val.
getAsSymbol(),
185 void TestAfterDivZeroChecker::checkEndFunction(
CheckerContext &C)
const {
188 DivZeroMapTy DivZeroes = State->get<DivZeroMap>();
189 if (DivZeroes.isEmpty())
192 DivZeroMapTy::Factory &F = State->get_context<DivZeroMap>();
198 DivZeroes = F.remove(DivZeroes, ZS);
203 void TestAfterDivZeroChecker::checkPreStmt(
const BinaryOperator *B,
215 void TestAfterDivZeroChecker::checkBranchCondition(
const Stmt *Condition,
217 if (
const BinaryOperator *B = dyn_cast<BinaryOperator>(Condition)) {
226 if (!IntLiteral || IntLiteral->
getValue() != 0)
230 if (hasDivZeroMap(Val, C))
233 }
else if (
const UnaryOperator *U = dyn_cast<UnaryOperator>(Condition)) {
234 if (U->getOpcode() ==
UO_LNot) {
237 dyn_cast<ImplicitCastExpr>(U->getSubExpr()))
238 Val = C.
getSVal(I->getSubExpr());
240 if (hasDivZeroMap(Val, C))
243 Val = C.
getSVal(U->getSubExpr());
244 if (hasDivZeroMap(Val, C))
249 dyn_cast<ImplicitCastExpr>(Condition)) {
252 if (hasDivZeroMap(Val, C))
257 if (hasDivZeroMap(Val, C))
virtual ProgramStateRef assume(ProgramStateRef state, DefinedSVal Cond, bool Assumption)=0
bool operator==(CanQual< T > x, CanQual< U > y)
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph). Uses the default CheckerContex...
#define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem)
FullSourceLoc asLocation() const
Symbolic value. These values used to capture symbolic execution of the program.
A builtin binary operation expression such as "x + y" or "x <= y".
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
llvm::APInt getValue() const
ExplodedNode * generateSink(ProgramStateRef State=nullptr, ExplodedNode *Pred=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a sink node. Generating a sink stops exploration of the given path.
ID
Defines the set of possible language-specific address spaces.
const ProgramStateRef & getState() const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
ConstraintManager & getConstraintManager()
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
CHECKER * registerChecker()
Used to register checkers.
bool isValid() const
Return true if this is a valid SourceLocation object.
bool operator<(DeclarationName LHS, DeclarationName RHS)
const StackFrameContext * getStackFrame() const
unsigned getBlockID() const
Get the blockID.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef. Otherwise, return 0.
static bool isComparisonOp(Opcode Opc)
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.