diff options
author | Zhongxing Xu <xuzhongxing@gmail.com> | 2009-11-06 13:30:44 +0000 |
---|---|---|
committer | Zhongxing Xu <xuzhongxing@gmail.com> | 2009-11-06 13:30:44 +0000 |
commit | ceeb02db9ad4232ea248a44192180d5bc7fe2653 (patch) | |
tree | a8f15d17caede8795040be5954e94aa870f31fa9 | |
parent | 48f5e63aec3f2fda7f1e75565bcbba08a9d6a14f (diff) |
Add a checker for CWE-466: Return of Pointer Value Outside of Expected Range.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86252 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Analysis/PathSensitive/Checker.h | 5 | ||||
-rw-r--r-- | lib/Analysis/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngineInternalChecks.cpp | 1 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngineInternalChecks.h | 1 | ||||
-rw-r--r-- | lib/Analysis/ReturnPointerRangeChecker.cpp | 86 | ||||
-rw-r--r-- | test/Analysis/region-only-test.c | 7 |
6 files changed, 101 insertions, 0 deletions
diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h index 2564a73089..a87d72b60e 100644 --- a/include/clang/Analysis/PathSensitive/Checker.h +++ b/include/clang/Analysis/PathSensitive/Checker.h @@ -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; } diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt index 111f273df6..1871b54a0d 100644 --- a/lib/Analysis/CMakeLists.txt +++ b/lib/Analysis/CMakeLists.txt @@ -36,6 +36,7 @@ add_clang_library(clangAnalysis PathDiagnostic.cpp RangeConstraintManager.cpp RegionStore.cpp + ReturnPointerRangeChecker.cpp ReturnStackAddressChecker.cpp ReturnUndefChecker.cpp SVals.cpp diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp index 4bb5d226d1..b18e58dea2 100644 --- a/lib/Analysis/GRExprEngineInternalChecks.cpp +++ b/lib/Analysis/GRExprEngineInternalChecks.cpp @@ -405,6 +405,7 @@ void GRExprEngine::RegisterInternalChecks() { // object. RegisterReturnStackAddressChecker(*this); RegisterReturnUndefChecker(*this); + RegisterReturnPointerRangeChecker(*this); registerCheck(new AttrNonNullChecker()); registerCheck(new UndefinedArgChecker()); registerCheck(new UndefinedAssignmentChecker()); diff --git a/lib/Analysis/GRExprEngineInternalChecks.h b/lib/Analysis/GRExprEngineInternalChecks.h index 622b5ab110..b4a00d2e13 100644 --- a/lib/Analysis/GRExprEngineInternalChecks.h +++ b/lib/Analysis/GRExprEngineInternalChecks.h @@ -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 index 0000000000..4ca72716a8 --- /dev/null +++ b/lib/Analysis/ReturnPointerRangeChecker.cpp @@ -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); + } +} diff --git a/test/Analysis/region-only-test.c b/test/Analysis/region-only-test.c index 8908adb105..b1e70a9054 100644 --- a/test/Analysis/region-only-test.c +++ b/test/Analysis/region-only-test.c @@ -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}} +} |