DivZeroChecker.cpp revision 218893
1109808Spdeuskar//== DivZeroChecker.cpp - Division by zero checker --------------*- C++ -*--==// 287191Spdeuskar// 3115211Sru// The LLVM Compiler Infrastructure 4109808Spdeuskar// 5109808Spdeuskar// This file is distributed under the University of Illinois Open Source 687191Spdeuskar// License. See LICENSE.TXT for details. 7109808Spdeuskar// 8109808Spdeuskar//===----------------------------------------------------------------------===// 9109808Spdeuskar// 10109808Spdeuskar// This defines DivZeroChecker, a builtin check in ExprEngine that performs 11109808Spdeuskar// checks for division by zeros. 12109808Spdeuskar// 13109808Spdeuskar//===----------------------------------------------------------------------===// 14109808Spdeuskar 15109808Spdeuskar#include "InternalChecks.h" 16109808Spdeuskar#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 17109808Spdeuskar#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" 1897567Sru 1997567Sruusing namespace clang; 2097567Sruusing namespace ento; 21109808Spdeuskar 22109808Spdeuskarnamespace { 23109808Spdeuskarclass DivZeroChecker : public CheckerVisitor<DivZeroChecker> { 24109808Spdeuskar BuiltinBug *BT; 25109808Spdeuskarpublic: 26109808Spdeuskar DivZeroChecker() : BT(0) {} 27109808Spdeuskar static void *getTag(); 28109808Spdeuskar void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B); 2987191Spdeuskar}; 3095809Spdeuskar} // end anonymous namespace 3195809Spdeuskar 3287191Spdeuskarvoid ento::RegisterDivZeroChecker(ExprEngine &Eng) { 33100731Spdeuskar Eng.registerCheck(new DivZeroChecker()); 34226264Sglebius} 3587191Spdeuskar 3697567Sruvoid *DivZeroChecker::getTag() { 3787191Spdeuskar static int x; 3887191Spdeuskar return &x; 39139698Sbrueffer} 4087191Spdeuskar 41151046Strhodesvoid DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C, 42152569Sru const BinaryOperator *B) { 43148220Strhodes BinaryOperator::Opcode Op = B->getOpcode(); 44148145Strhodes if (Op != BO_Div && 4587191Spdeuskar Op != BO_Rem && 46148145Strhodes Op != BO_DivAssign && 47148145Strhodes Op != BO_RemAssign) 48151046Strhodes return; 49151046Strhodes 50148145Strhodes if (!B->getRHS()->getType()->isIntegerType() || 51148145Strhodes !B->getRHS()->getType()->isScalarType()) 52148145Strhodes return; 53148145Strhodes 5487191Spdeuskar SVal Denom = C.getState()->getSVal(B->getRHS()); 5587191Spdeuskar const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom); 5687191Spdeuskar 57135015Sbrueffer // Divide-by-undefined handled in the generic checking for uses of 58139698Sbrueffer // undefined values. 59183653Ssimon if (!DV) 60183653Ssimon return; 6187191Spdeuskar 62162336Sbrueffer // Check for divide by zero. 63162336Sbrueffer ConstraintManager &CM = C.getConstraintManager(); 64162336Sbrueffer const GRState *stateNotZero, *stateZero; 65208098Smarius llvm::tie(stateNotZero, stateZero) = CM.assumeDual(C.getState(), *DV); 66208098Smarius 67208098Smarius if (stateZero && !stateNotZero) { 68208098Smarius if (ExplodedNode *N = C.generateSink(stateZero)) { 69208098Smarius if (!BT) 70135015Sbrueffer BT = new BuiltinBug("Division by zero"); 7197567Sru 7287191Spdeuskar EnhancedBugReport *R = 7387191Spdeuskar new EnhancedBugReport(*BT, BT->getDescription(), N); 7497567Sru 7597567Sru R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, 7697567Sru bugreporter::GetDenomExpr(N)); 7792574Sru 7887191Spdeuskar C.EmitReport(R); 7990628Spdeuskar } 8087191Spdeuskar return; 8187191Spdeuskar } 8290628Spdeuskar 8390628Spdeuskar // If we get here, then the denom should not be zero. We abandon the implicit 8487191Spdeuskar // zero denom case for now. 85100731Spdeuskar C.addTransition(stateNotZero); 8687191Spdeuskar} 8787191Spdeuskar