martong updated this revision to Diff 333508.
martong marked 5 inline comments as done.
martong added a comment.

- Use isZeroConstant()
- Make trackRValueExpression private (static function)
- Fix clang-tidy report: auto *BO  --->  const auto *BO


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D99344

Files:
  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,44 @@
   return N;
 }
 
+/// Attempts to add visitors to track an RValue expression back to its point of
+/// origin. Works similarly to trackExpressionValue, but accepts only RValues.
+static void trackRValueExpression(const ExplodedNode *InputNode, const Expr *E,
+                                  PathSensitiveBugReport &report,
+                                  bugreporter::TrackingKind TKind,
+                                  bool EnableNullFPSuppression) {
+  assert(E->isRValue() && "The expression is not an rvalue!");
+  const ExplodedNode *RVNode = findNodeForExpression(InputNode, E);
+  if (!RVNode)
+    return;
+  ProgramStateRef RVState = RVNode->getState();
+  SVal V = RVState->getSValAsScalarOrLoc(E, RVNode->getLocationContext());
+  const auto *BO = dyn_cast<BinaryOperator>(E);
+  if (!BO)
+    return;
+  if (!V.isZeroConstant())
+    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 (LHSV.isZeroConstant())
+      trackExpressionValue(InputNode, BO->getLHS(), report, TKind,
+                           EnableNullFPSuppression);
+    if (RHSV.isZeroConstant())
+      trackExpressionValue(InputNode, BO->getRHS(), report, TKind,
+                           EnableNullFPSuppression);
+  } else { // Track only the LHS of divisions.
+    if (LHSV.isZeroConstant())
+      trackExpressionValue(InputNode, BO->getLHS(), report, TKind,
+                           EnableNullFPSuppression);
+  }
+}
+
 bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode,
                                        const Expr *E,
                                        PathSensitiveBugReport &report,
@@ -2069,6 +2107,11 @@
             loc::MemRegionVal(RegionRVal), /*assumption=*/false));
     }
   }
+
+  if (Inner->isRValue())
+    trackRValueExpression(LVNode, Inner, report, TKind,
+                          EnableNullFPSuppression);
+
   return true;
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to