martong updated this revision to Diff 333346.
martong added a comment.

- Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D99344/new/

https://reviews.llvm.org/D99344

Files:
  clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
  clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
  clang/test/Analysis/division-by-zero-track-zero.c
  clang/test/Analysis/division-by-zero-track-zero.cpp
  clang/test/Analysis/nullptr.cpp

Index: clang/test/Analysis/nullptr.cpp
===================================================================
--- clang/test/Analysis/nullptr.cpp
+++ clang/test/Analysis/nullptr.cpp
@@ -64,7 +64,7 @@
 
 typedef __INTPTR_TYPE__ intptr_t;
 void zoo1multiply() {
-  char **p = 0; // FIXME-should-be-note:{{'p' initialized to a null pointer value}}
+  char **p = 0; // expected-note{{'p' initialized to a null pointer value}}
   delete *((char **)((intptr_t)p * 2)); // expected-warning{{Dereference of null pointer}}
                    // expected-note@-1{{Dereference of null pointer}}
 }
Index: clang/test/Analysis/division-by-zero-track-zero.cpp
===================================================================
--- /dev/null
+++ clang/test/Analysis/division-by-zero-track-zero.cpp
@@ -0,0 +1,98 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core \
+// RUN:   -analyzer-output=text \
+// RUN:   -verify %s
+
+namespace test_tracking_of_lhs_multiplier {
+  int f(int x, int y) {
+    bool p0 = x < 0;  // expected-note {{Assuming 'x' is >= 0}} \
+                      // expected-note {{'p0' initialized to 0}}
+    int div = p0 * y; // expected-note {{'div' initialized to 0}}
+    return 1 / div;   // expected-note {{Division by zero}} \
+                      // expected-warning {{Division by zero}}
+  }
+} // namespace test_tracking_of_lhs_multiplier
+
+namespace test_tracking_of_rhs_multiplier {
+  int f(int x, int y) {
+    bool p0 = x < 0;  // expected-note {{Assuming 'x' is >= 0}} \
+                      // expected-note {{'p0' initialized to 0}}
+    int div = y * p0; // expected-note {{'div' initialized to 0}}
+    return 1 / div;   // expected-note {{Division by zero}} \
+                      // expected-warning {{Division by zero}}
+  }
+} // namespace test_tracking_of_rhs_multiplier
+
+namespace test_tracking_of_nested_multiplier {
+  int f(int x, int y, int z) {
+    bool p0 = x < 0;  // expected-note {{Assuming 'x' is >= 0}} \
+                      // expected-note {{'p0' initialized to 0}}
+    int div = y*z*p0; // expected-note {{'div' initialized to 0}}
+    return 1 / div;   // expected-note {{Division by zero}} \
+                      // expected-warning {{Division by zero}}
+  }
+} // namespace test_tracking_of_nested_multiplier
+
+namespace test_tracking_through_multiple_stmts {
+  int f(int x, int y) {
+    bool p0 = x < 0;      // expected-note {{Assuming 'x' is >= 0}}
+    bool p1 = p0 ? 0 : 1; // expected-note {{'p0' is false}} \
+                          // expected-note {{'?' condition is false}}
+    bool p2 = 1 - p1;     // expected-note {{'p2' initialized to 0}}
+    int div = p2 * y;     // expected-note {{'div' initialized to 0}}
+    return 1 / div;       // expected-note {{Division by zero}} \
+                          // expected-warning {{Division by zero}}
+  }
+} // namespace test_tracking_through_multiple_stmts
+
+namespace test_tracking_both_lhs_and_rhs {
+  int f(int x, int y) {
+    bool p0 = x < 0;   // expected-note {{Assuming 'x' is >= 0}} \
+                       // expected-note {{'p0' initialized to 0}}
+    bool p1 = y < 0;   // expected-note {{Assuming 'y' is >= 0}} \
+                       // expected-note {{'p1' initialized to 0}}
+    int div = p0 * p1; // expected-note {{'div' initialized to 0}}
+    return 1 / div;    // expected-note {{Division by zero}} \
+                       // expected-warning {{Division by zero}}
+  }
+} // namespace test_tracking_both_lhs_and_rhs
+
+namespace test_tracking_of_multiplier_and_parens {
+  int f(int x, int y, int z) {
+    bool p0 = x < 0;    // expected-note {{Assuming 'x' is >= 0}} \
+                        // expected-note {{'p0' initialized to 0}}
+    int div = y*(z*p0); // expected-note {{'div' initialized to 0}}
+    return 1 / div;     // expected-note {{Division by zero}} \
+                        // expected-warning {{Division by zero}}
+  }
+} // namespace test_tracking_of_multiplier_and_parens
+
+namespace test_tracking_of_divisible {
+  int f(int x, int y) {
+    bool p0 = x < 0;    // expected-note {{Assuming 'x' is >= 0}} \
+                        // expected-note {{'p0' initialized to 0}}
+    int div = p0 / y;   // expected-note {{'div' initialized to 0}}
+    return 1 / div;     // expected-note {{Division by zero}} \
+                        // expected-warning {{Division by zero}}
+  }
+} // namespace test_tracking_of_divisible
+
+namespace test_tracking_of_modulo {
+  int f(int x, int y) {
+    bool p0 = x < 0;    // expected-note {{Assuming 'x' is >= 0}} \
+                        // expected-note {{'p0' initialized to 0}}
+    int div = p0 % y;   // expected-note {{'div' initialized to 0}}
+    return 1 / div;     // expected-note {{Division by zero}} \
+                        // expected-warning {{Division by zero}}
+  }
+} // namespace test_tracking_of_modulo
+
+namespace test_tracking_of_assignment {
+  int f(int x) {
+    bool p0 = x < 0;    // expected-note {{Assuming 'x' is >= 0}} \
+                        // expected-note {{'p0' initialized to 0}}
+    int div = 1;
+    div *= p0;          // expected-note {{The value 0 is assigned to 'div'}}
+    return 1 / div;     // expected-note {{Division by zero}} \
+                        // expected-warning {{Division by zero}}
+  }
+} // namespace test_tracking_of_assignment
Index: clang/test/Analysis/division-by-zero-track-zero.c
===================================================================
--- /dev/null
+++ clang/test/Analysis/division-by-zero-track-zero.c
@@ -0,0 +1,11 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core \
+// RUN:   -analyzer-output=text \
+// RUN:   -verify %s
+
+int track_mul_lhs_0(int x, int y) {
+  int p0 = x < 0;   // expected-note {{Assuming 'x' is >= 0}} \
+                    // expected-note {{'p0' initialized to 0}}
+  int div = p0 * y; // expected-note {{'div' initialized to 0}}
+  return 1 / div;   // expected-note {{Division by zero}} \
+                    // expected-warning {{Division by zero}}
+}
Index: clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -1924,6 +1924,62 @@
   return N;
 }
 
+void bugreporter::trackRValueExpression(const ExplodedNode *InputNode,
+                                        const Expr *E,
+                                        PathSensitiveBugReport &report,
+                                        bugreporter::TrackingKind TKind,
+                                        bool EnableNullFPSuppression) {
+  if (!E->isRValue())
+    return;
+  const ExplodedNode *RVNode = findNodeForExpression(InputNode, E);
+  if (!RVNode)
+    return;
+  ProgramStateRef RVState = RVNode->getState();
+  SVal V = RVState->getSValAsScalarOrLoc(E, RVNode->getLocationContext());
+  auto *BO = dyn_cast<BinaryOperator>(E);
+  if (!BO)
+    return;
+  ProgramStateManager &Mgr = RVState->getStateManager();
+  SValBuilder &SVB = Mgr.getSValBuilder();
+  BasicValueFactory &BVF = SVB.getBasicValueFactory();
+
+  auto IsZero = [&BVF](const Optional<nonloc::ConcreteInt> &CI) {
+    if (!CI)
+      return false;
+    const llvm::APSInt &Zero = BVF.getValue(0, BVF.getContext().IntTy);
+    // Do the comparison with the same canonical ASPInt.
+    return CI->getValue() == BVF.Convert(CI->getValue(), Zero);
+  };
+
+  auto CI = V.getAs<nonloc::ConcreteInt>();
+  if (!IsZero(CI))
+    return;
+
+  if (!BO->isMultiplicativeOp())
+    return;
+
+  SVal RHSV = RVState->getSVal(BO->getRHS(), RVNode->getLocationContext());
+  SVal LHSV = RVState->getSVal(BO->getLHS(), RVNode->getLocationContext());
+
+  // Track both LHS and RHS of a multiplication.
+  if (BO->getOpcode() == BO_Mul || BO->getOpcode() == BO_MulAssign) {
+    if (IsZero(LHSV.getAs<nonloc::ConcreteInt>())) {
+      trackExpressionValue(InputNode, BO->getLHS(), report, TKind,
+                           EnableNullFPSuppression);
+    }
+    if (IsZero(RHSV.getAs<nonloc::ConcreteInt>())) {
+      trackExpressionValue(InputNode, BO->getRHS(), report, TKind,
+                           EnableNullFPSuppression);
+    }
+    // Track only the LHS of divisions.
+  } else {
+    if (IsZero(LHSV.getAs<nonloc::ConcreteInt>())) {
+      trackExpressionValue(InputNode, BO->getLHS(), report, TKind,
+                           EnableNullFPSuppression);
+    }
+  }
+}
+
 bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode,
                                        const Expr *E,
                                        PathSensitiveBugReport &report,
@@ -2069,6 +2125,9 @@
             loc::MemRegionVal(RegionRVal), /*assumption=*/false));
     }
   }
+
+  trackRValueExpression(LVNode, Inner, report, TKind, EnableNullFPSuppression);
+
   return true;
 }
 
Index: clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
+++ clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
@@ -116,6 +116,13 @@
                           TrackingKind TKind = TrackingKind::Thorough,
                           bool EnableNullFPSuppression = true);
 
+/// Attempts to add visitors to track an RValue expression back to its point of
+/// origin. Works similarly to trackExpressionValue, but accepts only RValues.
+void trackRValueExpression(const ExplodedNode *N, const Expr *E,
+                           PathSensitiveBugReport &R,
+                           TrackingKind TKind = TrackingKind::Thorough,
+                           bool EnableNullFPSuppression = true);
+
 const Expr *getDerefExpr(const Stmt *S);
 
 } // namespace bugreporter
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to