19#include "llvm/ADT/FoldingSet.h"
35 : ZeroSymbol(S),
BlockID(B), SFC(SFC) {}
40 return BlockID ==
X.BlockID && SFC ==
X.SFC && ZeroSymbol ==
X.ZeroSymbol;
44 if (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 {
78class TestAfterDivZeroChecker
79 :
public Checker<check::PreStmt<BinaryOperator>, check::BranchCondition,
81 const BugType DivZeroBug{
this,
"Division by zero"};
102 const Expr *
E =
nullptr;
107 if (Op == BO_Div || Op == BO_Rem || Op == BO_DivAssign ||
108 Op == BO_RemAssign) {
117 if (ZeroSymbol == S.getAsSymbol() && SFC == Succ->
getStackFrame()) {
128 return std::make_shared<PathDiagnosticEventPiece>(
129 L,
"Division with compared value made here");
136 std::optional<DefinedSVal> DSV = S.getAs<
DefinedSVal>();
142 return !CM.
assume(
C.getState(), *DSV,
true);
152 State->add<DivZeroMap>(ZeroState(SR,
C.getBlockID(),
C.getStackFrame()));
153 C.addTransition(State);
156bool TestAfterDivZeroChecker::hasDivZeroMap(
SVal Var,
162 ZeroState ZS(SR,
C.getBlockID(),
C.getStackFrame());
163 return C.getState()->contains<DivZeroMap>(ZS);
168 auto R = std::make_unique<PathSensitiveBugReport>(
170 "Value being compared against zero has already been used "
174 R->addVisitor(std::make_unique<DivisionBRVisitor>(Val.
getAsSymbol(),
176 C.emitReport(std::move(R));
180void TestAfterDivZeroChecker::checkEndFunction(
const ReturnStmt *,
184 DivZeroMapTy DivZeroes = State->get<DivZeroMap>();
185 if (DivZeroes.isEmpty())
188 DivZeroMapTy::Factory &F = State->get_context<DivZeroMap>();
189 for (
const ZeroState &ZS : DivZeroes) {
190 if (ZS.getStackFrameContext() ==
C.getStackFrame())
191 DivZeroes = F.remove(DivZeroes, ZS);
193 C.addTransition(State->set<DivZeroMap>(DivZeroes));
196void TestAfterDivZeroChecker::checkPreStmt(
const BinaryOperator *B,
199 if (Op == BO_Div || Op == BO_Rem || Op == BO_DivAssign ||
200 Op == BO_RemAssign) {
208void TestAfterDivZeroChecker::checkBranchCondition(
const Stmt *
Condition,
215 IntLiteral = dyn_cast<IntegerLiteral>(B->
getLHS());
219 if (!IntLiteral || IntLiteral->
getValue() != 0)
223 if (hasDivZeroMap(Val,
C))
227 if (
U->getOpcode() == UO_LNot) {
230 dyn_cast<ImplicitCastExpr>(
U->getSubExpr()))
231 Val =
C.getSVal(I->getSubExpr());
233 if (hasDivZeroMap(Val,
C))
236 Val =
C.getSVal(
U->getSubExpr());
237 if (hasDivZeroMap(Val,
C))
243 SVal Val =
C.getSVal(IE->getSubExpr());
245 if (hasDivZeroMap(Val,
C))
250 if (hasDivZeroMap(Val,
C))
260bool ento::shouldRegisterTestAfterDivZeroChecker(
const CheckerManager &mgr) {
#define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem)
Declares an immutable set of type NameTy, suitable for placement into the ProgramState.
llvm::APInt getValue() const
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isComparisonOp(Opcode Opc)
This represents one expression.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
bool isValid() const
Return true if this is a valid SourceLocation object.
It represents a stack frame of the call stack (based on CallEvent).
Stmt - This represents one statement.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
const SourceManager & getSourceManager() const
BugReporterVisitors are used to add custom diagnostics along a path.
virtual void Profile(llvm::FoldingSetNodeID &ID) const =0
virtual PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC, PathSensitiveBugReport &BR)=0
Return a diagnostic piece which should be associated with the given node.
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
ProgramStateRef assume(ProgramStateRef state, DefinedSVal Cond, bool Assumption)
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
const StackFrameContext * getStackFrame() const
SVal getSVal(const Stmt *S) const
Get the value of an arbitrary expression at this node.
std::optional< T > getLocationAs() const &
FullSourceLoc asLocation() const
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
BlockID
The various types of blocks that can occur within a API notes file.
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
The JSON file list parser is used to communicate input to InstallAPI.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.