[analyzer] Add taint awareness to DivZeroChecker.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148566 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
index 12fd6f4..b9ed384 100644
--- a/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
@@ -24,11 +24,31 @@
 namespace {
 class DivZeroChecker : public Checker< check::PreStmt<BinaryOperator> > {
   mutable llvm::OwningPtr<BuiltinBug> BT;
+  void reportBug(const char *Msg,
+                 const ProgramState *StateZero,
+                 CheckerContext &C) const ;
 public:
   void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
 };  
 } // end anonymous namespace
 
+void DivZeroChecker::reportBug(const char *Msg,
+                               const ProgramState *StateZero,
+                               CheckerContext &C) const {
+  if (ExplodedNode *N = C.generateSink(StateZero)) {
+    if (!BT)
+      BT.reset(new BuiltinBug(Msg));
+
+    BugReport *R =
+      new BugReport(*BT, BT->getDescription(), N);
+
+    R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
+                                 bugreporter::GetDenomExpr(N)));
+
+    C.EmitReport(R);
+  }
+}
+
 void DivZeroChecker::checkPreStmt(const BinaryOperator *B,
                                   CheckerContext &C) const {
   BinaryOperator::Opcode Op = B->getOpcode();
@@ -57,18 +77,13 @@
 
   if (!stateNotZero) {
     assert(stateZero);
-    if (ExplodedNode *N = C.generateSink(stateZero)) {
-      if (!BT)
-        BT.reset(new BuiltinBug("Division by zero"));
+    reportBug("Division by zero", stateZero, C);
+    return;
+  }
 
-      BugReport *R = 
-        new BugReport(*BT, BT->getDescription(), N);
-
-      R->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
-                                   bugreporter::GetDenomExpr(N)));
-
-      C.EmitReport(R);
-    }
+  bool TaintedD = C.getState()->isTainted(*DV);
+  if ((stateNotZero && stateZero && TaintedD)) {
+    reportBug("Division by a tainted value, possibly zero", stateZero, C);
     return;
   }
 
diff --git a/test/Analysis/taint-generic.c b/test/Analysis/taint-generic.c
index 47bdb4e..65e519e 100644
--- a/test/Analysis/taint-generic.c
+++ b/test/Analysis/taint-generic.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1  -analyze -analyzer-checker=experimental.security.taint,experimental.security.ArrayBoundV2 -Wno-format-security -verify %s
+// RUN: %clang_cc1  -analyze -analyzer-checker=experimental.security.taint,core,experimental.security.ArrayBoundV2 -Wno-format-security -verify %s
 
 int scanf(const char *restrict format, ...);
 int getchar(void);
@@ -49,7 +49,7 @@
 void bufferScanfArithmetic2(int x) {
   int n;
   scanf("%d", &n);
-  int m = 100 / (n + 3) * x;
+  int m = 100 - (n + 3) * x;
   Buffer[m] = 1; // expected-warning {{Out of bound memory access }}
 }
 
@@ -64,7 +64,7 @@
 }
 
 void scanfArg() {
-  int t;
+  int t = 0;
   scanf("%d", t); // expected-warning {{conversion specifies type 'int *' but the argument has type 'int'}}
 }
 
@@ -171,3 +171,8 @@
   execl(buffer, "filename", 0); // no-warning
 }
 
+int testDivByZero() {
+  int x;
+  scanf("%d", &x);
+  return 5/x; // expected-warning {{Division by a tainted value, possibly zero}}
+}