DivZeroChecker.cpp revision 04291a7c76e16a2dc5433c80c3d13c826bf372dc
1//== DivZeroChecker.cpp - Division by zero checker --------------*- C++ -*--==// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This defines DivZeroChecker, a builtin check in ExprEngine that performs 11// checks for division by zeros. 12// 13//===----------------------------------------------------------------------===// 14 15#include "InternalChecks.h" 16#include "clang/StaticAnalyzer/BugReporter/BugType.h" 17#include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h" 18 19using namespace clang; 20using namespace ento; 21 22namespace { 23class DivZeroChecker : public CheckerVisitor<DivZeroChecker> { 24 BuiltinBug *BT; 25public: 26 DivZeroChecker() : BT(0) {} 27 static void *getTag(); 28 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); 29}; 30} // end anonymous namespace 31 32void ento::RegisterDivZeroChecker(ExprEngine &Eng) { 33 Eng.registerCheck(new DivZeroChecker()); 34} 35 36void *DivZeroChecker::getTag() { 37 static int x; 38 return &x; 39} 40 41void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C, 42 const BinaryOperator *B) { 43 BinaryOperator::Opcode Op = B->getOpcode(); 44 if (Op != BO_Div && 45 Op != BO_Rem && 46 Op != BO_DivAssign && 47 Op != BO_RemAssign) 48 return; 49 50 if (!B->getRHS()->getType()->isIntegerType() || 51 !B->getRHS()->getType()->isScalarType()) 52 return; 53 54 SVal Denom = C.getState()->getSVal(B->getRHS()); 55 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom); 56 57 // Divide-by-undefined handled in the generic checking for uses of 58 // undefined values. 59 if (!DV) 60 return; 61 62 // Check for divide by zero. 63 ConstraintManager &CM = C.getConstraintManager(); 64 const GRState *stateNotZero, *stateZero; 65 llvm::tie(stateNotZero, stateZero) = CM.assumeDual(C.getState(), *DV); 66 67 if (stateZero && !stateNotZero) { 68 if (ExplodedNode *N = C.generateSink(stateZero)) { 69 if (!BT) 70 BT = new BuiltinBug("Division by zero"); 71 72 EnhancedBugReport *R = 73 new EnhancedBugReport(*BT, BT->getDescription(), N); 74 75 R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, 76 bugreporter::GetDenomExpr(N)); 77 78 C.EmitReport(R); 79 } 80 return; 81 } 82 83 // If we get here, then the denom should not be zero. We abandon the implicit 84 // zero denom case for now. 85 C.addTransition(stateNotZero); 86} 87