]> granicus.if.org Git - clang/commitdiff
Add checker for CWE-469: Use of Pointer Subtraction to Determine Size. This
authorZhongxing Xu <xuzhongxing@gmail.com>
Mon, 9 Nov 2009 05:34:10 +0000 (05:34 +0000)
committerZhongxing Xu <xuzhongxing@gmail.com>
Mon, 9 Nov 2009 05:34:10 +0000 (05:34 +0000)
checker does not build sink nodes. Because svaluator computes an unknown value
for the subtraction now.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86517 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/GRExprEngineInternalChecks.cpp
lib/Analysis/GRExprEngineInternalChecks.h
lib/Analysis/PointerSubChecker.cpp [new file with mode: 0644]
test/Analysis/ptr-arith.c

index 41ad018dcf80c8f77d9f3ca82e933ce2db5c812d..8977b198233ccf093acd585763e943e795796af1 100644 (file)
@@ -412,6 +412,7 @@ void GRExprEngine::RegisterInternalChecks() {
   RegisterDivZeroChecker(*this);
   RegisterReturnStackAddressChecker(*this);
   RegisterReturnUndefChecker(*this);
+  RegisterPointerSubChecker(*this);
 
   // Note that this must be registered after ReturnStackAddressChecker.
   RegisterReturnPointerRangeChecker(*this);
index 42753b94fd3330b8c0e0b1c9ed9bef8c4151a6c9..6d080dc466756a5658798a77e07b1beb78416a04 100644 (file)
@@ -24,6 +24,6 @@ void RegisterReturnPointerRangeChecker(GRExprEngine &Eng);
 void RegisterReturnStackAddressChecker(GRExprEngine &Eng);  
 void RegisterReturnUndefChecker(GRExprEngine &Eng);
 void RegisterVLASizeChecker(GRExprEngine &Eng);
-  
+void RegisterPointerSubChecker(GRExprEngine &Eng);  
 } // end clang namespace
 #endif
diff --git a/lib/Analysis/PointerSubChecker.cpp b/lib/Analysis/PointerSubChecker.cpp
new file mode 100644 (file)
index 0000000..ebe051e
--- /dev/null
@@ -0,0 +1,71 @@
+//=== PointerSubChecker.cpp - Pointer subtraction checker ------*- C++ -*--===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This files defines PointerSubChecker, a builtin checker that checks for
+// pointer subtractions on two pointers pointing to different memory chunks. 
+// This check corresponds to CWE-469.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "GRExprEngineInternalChecks.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN PointerSubChecker 
+  : public CheckerVisitor<PointerSubChecker> {
+  BuiltinBug *BT;
+public:
+  PointerSubChecker() : BT(0) {}
+  static void *getTag();
+  void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+};
+}
+
+void *PointerSubChecker::getTag() {
+  static int x;
+  return &x;
+}
+
+void PointerSubChecker::PreVisitBinaryOperator(CheckerContext &C,
+                                               const BinaryOperator *B) {
+  // When doing pointer subtraction, if the two pointers do not point to the
+  // same memory chunk, emit a warning.
+  if (B->getOpcode() != BinaryOperator::Sub)
+    return;
+
+  const GRState *state = C.getState();
+  SVal LV = state->getSVal(B->getLHS());
+  SVal RV = state->getSVal(B->getRHS());
+
+  const MemRegion *LR = LV.getAsRegion();
+  const MemRegion *RR = RV.getAsRegion();
+
+  if (!(LR && RR) || (LR == RR))
+    return;
+
+  // We don't reason about SymbolicRegions for now.
+  if (isa<SymbolicRegion>(LR) || isa<SymbolicRegion>(RR))
+    return;
+
+  if (ExplodedNode *N = C.GenerateNode(B)) {
+    if (!BT)
+      BT = new BuiltinBug("Pointer subtraction", 
+                          "Subtraction of two pointers that do not point to the same memory chunk may cause incorrect result.");
+    RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription().c_str(),
+                                             N);
+    R->addRange(B->getSourceRange());
+    C.EmitReport(R);
+  }
+}
+
+void clang::RegisterPointerSubChecker(GRExprEngine &Eng) {
+  Eng.registerCheck(new PointerSubChecker());
+}
index d08d7e9471977bc73d9681a170006d123cd0b9e1..fc404e282e60eb25212f3da0faae5d23ee23c0ef 100644 (file)
@@ -31,3 +31,8 @@ domain_port (const char *domain_b, const char *domain_e,
     port = 10 * port + (*p - '0');
   return port;
 }
+
+void f3() {
+  int x, y;
+  int d = &y - &x; // expected-warning{{Subtraction of two pointers that do not point to the same memory chunk may cause incorrect result.}}
+}