steakhal created this revision.
steakhal added reviewers: NoQ, xazax.hun, donat.nagy, Szelethus.
Herald added subscribers: manas, ASDenysPetrov, martong, dkrupp, 
mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware.
Herald added a project: All.
steakhal requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

After this patch, we no longer need the check::Location callback, as we
caught bugs earlier when forming bad references - aka. before loading or
binding anything to it.

(CWE-122 Heap Based Buffer Overflow: CWE-805-class-loop)

Depends on D159106 <https://reviews.llvm.org/D159106>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D159107

Files:
  clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
  clang/test/Analysis/out-of-bounds-new.cpp

Index: clang/test/Analysis/out-of-bounds-new.cpp
===================================================================
--- clang/test/Analysis/out-of-bounds-new.cpp
+++ clang/test/Analysis/out-of-bounds-new.cpp
@@ -176,3 +176,63 @@
       break;
   }
 }
+
+void test_memberwise_copy() {
+  ManyInts dst[1];
+  ManyInts src[2] = {5};
+
+  dst[0] = src[0]; // ok
+  dst[0].a = src[0].a; // ok
+
+  // Positive indexing:
+  switch (rng()) {
+    default: break;
+    case 0: {
+      auto &z = dst[1]; // expected-warning {{Out of bound memory access (access exceeds upper limit of memory block)}}
+      break;
+    }
+    case 1: {
+      dst[1].a = src[1].a; // expected-warning {{Out of bound memory access (access exceeds upper limit of memory block)}}
+      break;
+    }
+    case 2: {
+      auto &z = *(dst + 1); // expected-warning {{Out of bound memory access (access exceeds upper limit of memory block)}}
+      break;
+    }
+    case 3: {
+      auto &z = *dst;
+      auto &zz = 1[&z]; // expected-warning {{Out of bound memory access (access exceeds upper limit of memory block)}}
+      break;
+    }
+    case 4: {
+      dst[1] = src[1]; // expected-warning {{Out of bound memory access (access exceeds upper limit of memory block)}}
+      break;
+    }
+  }
+
+  // Negative indexing:
+  switch (rng()) {
+    default: break;
+    case 0: {
+      auto &z = dst[-1]; // expected-warning {{Out of bound memory access (accessed memory precedes memory block)}}
+      break;
+    }
+    case 1: {
+      dst[-1].a = src[1].a; // expected-warning {{Out of bound memory access (accessed memory precedes memory block)}}
+      break;
+    }
+    case 2: {
+      auto &z = *(dst - 1); // expected-warning {{Out of bound memory access (accessed memory precedes memory block)}}
+      break;
+    }
+    case 3: {
+      auto &z = *dst;
+      auto &zz = (-1)[&z]; // expected-warning {{Out of bound memory access (accessed memory precedes memory block)}}
+      break;
+    }
+    case 4: {
+      dst[-1] = src[1]; // expected-warning {{Out of bound memory access (accessed memory precedes memory block)}}
+      break;
+    }
+  }
+}
Index: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
+++ clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
@@ -30,7 +30,9 @@
 using namespace taint;
 
 namespace {
-class ArrayBoundCheckerV2 : public Checker<check::Location, check::Bind> {
+class ArrayBoundCheckerV2
+    : public Checker<check::Bind, check::PostStmt<ArraySubscriptExpr>,
+                     check::PostStmt<UnaryOperator>> {
   mutable std::unique_ptr<BugType> BT;
   mutable std::unique_ptr<BugType> TaintBT;
 
@@ -46,9 +48,9 @@
   void impl(SVal Loc, bool isLoad, const Stmt *S, CheckerContext &C) const;
 
 public:
-  void checkLocation(SVal l, bool isLoad, const Stmt *S,
-                     CheckerContext &C) const;
   void checkBind(SVal Loc, SVal, const Stmt *S, CheckerContext &) const;
+  void checkPostStmt(const ArraySubscriptExpr *E, CheckerContext &C) const;
+  void checkPostStmt(const UnaryOperator *E, CheckerContext &C) const;
 };
 
 // FIXME: Eventually replace RegionRawOffset with this class.
@@ -142,13 +144,6 @@
   return {nullptr, nullptr};
 }
 
-void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad,
-                                        const Stmt* LoadS,
-                                        CheckerContext &checkerContext) const {
-  if (isLoad)
-    impl(location, isLoad, LoadS, checkerContext);
-}
-
 void ArrayBoundCheckerV2::checkBind(SVal Loc, SVal, const Stmt *S,
                                     CheckerContext &C) const {
   impl(Loc, /*isLoad=*/false, S, C);
@@ -375,6 +370,21 @@
   return std::nullopt;
 }
 
+void ArrayBoundCheckerV2::checkPostStmt(const ArraySubscriptExpr *E,
+                                        CheckerContext &C) const {
+  // TODO: Specialize the diagnostic message.
+  // It might not be a "load" operation.
+  impl(C.getSVal(E), /*isLoad=*/true, E, C);
+}
+void ArrayBoundCheckerV2::checkPostStmt(const UnaryOperator *E,
+                                        CheckerContext &C) const {
+  if (E->getOpcode() != UO_Deref)
+    return;
+  // TODO: Specialize the diagnostic message.
+  // It might not be a "load" operation.
+  impl(C.getSVal(E), /*isLoad=*/true, E, C);
+}
+
 void ento::registerArrayBoundCheckerV2(CheckerManager &mgr) {
   mgr.registerChecker<ArrayBoundCheckerV2>();
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to