Chris Lattner has strong opinions about directory
layout.  :)

Rename the 'EntoSA' directories to 'StaticAnalyzer'.

Internally we will still use the 'ento' namespace
for the analyzer engine (unless there are further
sabre rattlings...).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122514 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
new file mode 100644
index 0000000..1ba60f7
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
@@ -0,0 +1,79 @@
+//=== 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 "ExprEngineInternalChecks.h"
+#include "clang/StaticAnalyzer/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class 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() != BO_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))
+    return;
+
+  const MemRegion *BaseLR = LR->getBaseRegion();
+  const MemRegion *BaseRR = RR->getBaseRegion();
+
+  if (BaseLR == BaseRR)
+    return;
+
+  // Allow arithmetic on different symbolic regions.
+  if (isa<SymbolicRegion>(BaseLR) || isa<SymbolicRegion>(BaseRR))
+    return;
+
+  if (ExplodedNode *N = C.generateNode()) {
+    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(), N);
+    R->addRange(B->getSourceRange());
+    C.EmitReport(R);
+  }
+}
+
+void ento::RegisterPointerSubChecker(ExprEngine &Eng) {
+  Eng.registerCheck(new PointerSubChecker());
+}