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 "ExprEngineInternalChecks.h" 16 #include "clang/StaticAnalyzer/BugReporter/BugType.h" 17 #include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h" 18 19 using namespace clang; 20 using namespace ento; 21 22 namespace { 23 class DivZeroChecker : public CheckerVisitor<DivZeroChecker> { 24 BuiltinBug *BT; 25 public: 26 DivZeroChecker() : BT(0) {} 27 static void *getTag(); 28 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); 29 }; 30 } // end anonymous namespace 31 32 void ento::RegisterDivZeroChecker(ExprEngine &Eng) { 33 Eng.registerCheck(new DivZeroChecker()); 34 } 35 36 void *DivZeroChecker::getTag() { 37 static int x; 38 return &x; 39 } 40 41 void 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