]> granicus.if.org Git - clang/commitdiff
Add a checker for CWE-466: Return of Pointer Value Outside of Expected Range.
authorZhongxing Xu <xuzhongxing@gmail.com>
Fri, 6 Nov 2009 13:30:44 +0000 (13:30 +0000)
committerZhongxing Xu <xuzhongxing@gmail.com>
Fri, 6 Nov 2009 13:30:44 +0000 (13:30 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86252 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/PathSensitive/Checker.h
lib/Analysis/CMakeLists.txt
lib/Analysis/GRExprEngineInternalChecks.cpp
lib/Analysis/GRExprEngineInternalChecks.h
lib/Analysis/ReturnPointerRangeChecker.cpp [new file with mode: 0644]
test/Analysis/region-only-test.c

index 2564a73089b7c852f2c2eee35ba5e19157fd1605..a87d72b60e4e51f2e4634c53c57daed19108f08a 100644 (file)
@@ -64,6 +64,11 @@ public:
   ConstraintManager &getConstraintManager() {
       return Eng.getConstraintManager();
   }
+
+  StoreManager &getStoreManager() {
+    return Eng.getStoreManager();
+  }
+
   ExplodedNodeSet &getNodeSet() { return Dst; }
   GRStmtNodeBuilder &getNodeBuilder() { return B; }
   ExplodedNode *&getPredecessor() { return Pred; }
index 111f273df6c6964ff4bd1dcba65e7b5a1d8518b5..1871b54a0d424684dd8429d04dc48d1d7110ce42 100644 (file)
@@ -36,6 +36,7 @@ add_clang_library(clangAnalysis
   PathDiagnostic.cpp
   RangeConstraintManager.cpp
   RegionStore.cpp
+  ReturnPointerRangeChecker.cpp
   ReturnStackAddressChecker.cpp
   ReturnUndefChecker.cpp
   SVals.cpp
index 4bb5d226d17e4c7de9221bdfc92f77a47527796e..b18e58dea2e57bbace41c12b7a5ce7c2b17d9a3e 100644 (file)
@@ -405,6 +405,7 @@ void GRExprEngine::RegisterInternalChecks() {
   // object.
   RegisterReturnStackAddressChecker(*this);
   RegisterReturnUndefChecker(*this);
+  RegisterReturnPointerRangeChecker(*this);
   registerCheck(new AttrNonNullChecker());
   registerCheck(new UndefinedArgChecker());
   registerCheck(new UndefinedAssignmentChecker());
index 622b5ab1108f2c3aced8a6943aeca3fb63ba93d3..b4a00d2e1317ae34f70f77059eb9ec90a147545d 100644 (file)
@@ -21,6 +21,7 @@ class GRExprEngine;
 
 void RegisterReturnStackAddressChecker(GRExprEngine &Eng);
 void RegisterReturnUndefChecker(GRExprEngine &Eng);
+void RegisterReturnPointerRangeChecker(GRExprEngine &Eng);
   
 } // end clang namespace
 #endif
diff --git a/lib/Analysis/ReturnPointerRangeChecker.cpp b/lib/Analysis/ReturnPointerRangeChecker.cpp
new file mode 100644 (file)
index 0000000..4ca7271
--- /dev/null
@@ -0,0 +1,86 @@
+//== ReturnPointerRangeChecker.cpp ------------------------------*- C++ -*--==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ReturnPointerRangeChecker, which is a path-sensitive check
+// which looks for an out-of-bound pointer being returned to callers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GRExprEngineInternalChecks.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
+#include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+
+using namespace clang;
+
+namespace {
+class VISIBILITY_HIDDEN ReturnPointerRangeChecker : 
+    public CheckerVisitor<ReturnPointerRangeChecker> {      
+  BuiltinBug *BT;
+public:
+    ReturnPointerRangeChecker() : BT(0) {}
+    static void *getTag();
+    void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
+};
+}
+
+void clang::RegisterReturnPointerRangeChecker(GRExprEngine &Eng) {
+  Eng.registerCheck(new ReturnPointerRangeChecker());
+}
+
+void *ReturnPointerRangeChecker::getTag() {
+  static int x = 0; return &x;
+}
+
+void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
+                                                   const ReturnStmt *RS) {
+  const GRState *state = C.getState();
+
+  const Expr *RetE = RS->getRetValue();
+  if (!RetE)
+    return;
+  SVal V = state->getSVal(RetE);
+  const MemRegion *R = V.getAsRegion();
+
+  const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(R);
+  if (!ER)
+    return;  
+
+  DefinedOrUnknownSVal &Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
+
+  // Zero index is always in bound, this also passes ElementRegions created for
+  // pointer casts.
+  if (Idx.isZeroConstant())
+    return;
+
+  SVal NumVal = C.getStoreManager().getSizeInElements(state,
+                                                      ER->getSuperRegion());
+  DefinedOrUnknownSVal &NumElements = cast<DefinedOrUnknownSVal>(NumVal);
+
+  const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
+  const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
+  if (StOutBound && !StInBound) {
+    ExplodedNode *N = C.GenerateNode(RS, StOutBound, true);
+
+    if (!N)
+      return;
+  
+    if (!BT)
+      BT = new BuiltinBug("Return of Pointer Value Outside of Expected Range");
+  
+    // Generate a report for this bug.
+    RangedBugReport *report = 
+      new RangedBugReport(*BT, BT->getDescription().c_str(), N);
+
+    report->addRange(RS->getSourceRange());
+  
+    C.EmitReport(report);
+  }
+}
index 8908adb1057c77c29e5ac0aaeeacdc791f3f4a4e..b1e70a90546db36dd8db99db0b26d465ae40c4fb 100644 (file)
@@ -11,3 +11,10 @@ void foo(int* p) {
   if (p[0] == 1)
     (void)*x; // no-warning
 }
+
+int a[10];
+
+int *f0() {
+  int *p = a+10;
+  return p; // expected-warning{{Return of Pointer Value Outside of Expected Range}}
+}