blob: d795800d6f58cf6d550fb7e1ac9096b4d7120f9c [file] [log] [blame]
Zhongxing Xu9e56d232009-10-31 10:02:37 +00001//== 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 GRExprEngine that performs
11// checks for division by zeros.
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenek36df58a2009-11-06 20:47:51 +000015#include "GRExprEngineInternalChecks.h"
Benjamin Kramer5e2d2c22010-03-27 21:19:47 +000016#include "clang/Checker/BugReporter/BugType.h"
17#include "clang/Checker/PathSensitive/CheckerVisitor.h"
Zhongxing Xu9e56d232009-10-31 10:02:37 +000018
19using namespace clang;
20
Ted Kremenek36df58a2009-11-06 20:47:51 +000021namespace {
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000022class DivZeroChecker : public CheckerVisitor<DivZeroChecker> {
Ted Kremenek36df58a2009-11-06 20:47:51 +000023 BuiltinBug *BT;
24public:
25 DivZeroChecker() : BT(0) {}
26 static void *getTag();
27 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
28};
29} // end anonymous namespace
30
31void clang::RegisterDivZeroChecker(GRExprEngine &Eng) {
32 Eng.registerCheck(new DivZeroChecker());
33}
34
Zhongxing Xu9e56d232009-10-31 10:02:37 +000035void *DivZeroChecker::getTag() {
36 static int x;
37 return &x;
38}
39
40void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C,
41 const BinaryOperator *B) {
42 BinaryOperator::Opcode Op = B->getOpcode();
John McCall2de56d12010-08-25 11:45:40 +000043 if (Op != BO_Div &&
44 Op != BO_Rem &&
45 Op != BO_DivAssign &&
46 Op != BO_RemAssign)
Zhongxing Xu9e56d232009-10-31 10:02:37 +000047 return;
48
49 if (!B->getRHS()->getType()->isIntegerType() ||
50 !B->getRHS()->getType()->isScalarType())
51 return;
52
Ted Kremenek13976632010-02-08 16:18:51 +000053 SVal Denom = C.getState()->getSVal(B->getRHS());
Zhongxing Xu9e56d232009-10-31 10:02:37 +000054 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
55
56 // Divide-by-undefined handled in the generic checking for uses of
57 // undefined values.
58 if (!DV)
59 return;
60
61 // Check for divide by zero.
62 ConstraintManager &CM = C.getConstraintManager();
63 const GRState *stateNotZero, *stateZero;
Ted Kremenek28f47b92010-12-01 22:16:56 +000064 llvm::tie(stateNotZero, stateZero) = CM.assumeDual(C.getState(), *DV);
Zhongxing Xu9e56d232009-10-31 10:02:37 +000065
66 if (stateZero && !stateNotZero) {
Ted Kremenek19d67b52009-11-23 22:22:01 +000067 if (ExplodedNode *N = C.GenerateSink(stateZero)) {
Zhongxing Xu9e56d232009-10-31 10:02:37 +000068 if (!BT)
Ted Kremenek2c791bd2009-11-06 00:44:32 +000069 BT = new BuiltinBug("Division by zero");
Zhongxing Xu9e56d232009-10-31 10:02:37 +000070
71 EnhancedBugReport *R =
Benjamin Kramerd02e2322009-11-14 12:08:24 +000072 new EnhancedBugReport(*BT, BT->getDescription(), N);
Zhongxing Xu9e56d232009-10-31 10:02:37 +000073
74 R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
75 bugreporter::GetDenomExpr(N));
76
77 C.EmitReport(R);
78 }
79 return;
80 }
81
82 // If we get here, then the denom should not be zero. We abandon the implicit
83 // zero denom case for now.
Ted Kremenek19d67b52009-11-23 22:22:01 +000084 C.addTransition(stateNotZero);
Zhongxing Xu9e56d232009-10-31 10:02:37 +000085}