From: Ted Kremenek Date: Tue, 12 Apr 2011 17:21:33 +0000 (+0000) Subject: ArrayBoundCheckerV2: don't arbitrarily warn about indexing before the 0-index of... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=82cfc6849204b07e80f8ac71e33247f7df760032;p=clang ArrayBoundCheckerV2: don't arbitrarily warn about indexing before the 0-index of a symbolic region. In many cases that isn't really the base offset. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129366 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp index 2aef5c13c2..65a6e633dc 100644 --- a/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp +++ b/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp @@ -62,6 +62,22 @@ public: }; } +static SVal computeExtentBegin(SValBuilder &svalBuilder, + const MemRegion *region) { + while (true) + switch (region->getKind()) { + default: + return svalBuilder.makeZeroArrayIndex(); + case MemRegion::SymbolicRegionKind: + // FIXME: improve this later by tracking symbolic lower bounds + // for symbolic regions. + return UnknownVal(); + case MemRegion::ElementRegionKind: + region = cast(region)->getSuperRegion(); + continue; + } +} + void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad, CheckerContext &checkerContext) const { @@ -84,31 +100,36 @@ void ArrayBoundCheckerV2::checkLocation(SVal location, bool isLoad, if (!rawOffset.getRegion()) return; - // CHECK LOWER BOUND: Is byteOffset < 0? If so, we are doing a load/store + // CHECK LOWER BOUND: Is byteOffset < extent begin? + // If so, we are doing a load/store // before the first valid offset in the memory region. - SVal lowerBound - = svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(), - svalBuilder.makeZeroArrayIndex(), - svalBuilder.getConditionType()); + SVal extentBegin = computeExtentBegin(svalBuilder, rawOffset.getRegion()); + + if (isa(extentBegin)) { + SVal lowerBound + = svalBuilder.evalBinOpNN(state, BO_LT, rawOffset.getByteOffset(), + cast(extentBegin), + svalBuilder.getConditionType()); - NonLoc *lowerBoundToCheck = dyn_cast(&lowerBound); - if (!lowerBoundToCheck) - return; + NonLoc *lowerBoundToCheck = dyn_cast(&lowerBound); + if (!lowerBoundToCheck) + return; - const GRState *state_precedesLowerBound, *state_withinLowerBound; - llvm::tie(state_precedesLowerBound, state_withinLowerBound) = + const GRState *state_precedesLowerBound, *state_withinLowerBound; + llvm::tie(state_precedesLowerBound, state_withinLowerBound) = state->assume(*lowerBoundToCheck); - // Are we constrained enough to definitely precede the lower bound? - if (state_precedesLowerBound && !state_withinLowerBound) { - reportOOB(checkerContext, state_precedesLowerBound, OOB_Precedes); - return; - } + // Are we constrained enough to definitely precede the lower bound? + if (state_precedesLowerBound && !state_withinLowerBound) { + reportOOB(checkerContext, state_precedesLowerBound, OOB_Precedes); + return; + } - // Otherwise, assume the constraint of the lower bound. - assert(state_withinLowerBound); - state = state_withinLowerBound; + // Otherwise, assume the constraint of the lower bound. + assert(state_withinLowerBound); + state = state_withinLowerBound; + } do { // CHECK UPPER BOUND: Is byteOffset >= extent(baseRegion)? If so, @@ -232,9 +253,11 @@ RegionRawOffsetV2 RegionRawOffsetV2::computeOffset(const GRState *state, while (region) { switch (region->getKind()) { default: { - if (const SubRegion *subReg = dyn_cast(region)) + if (const SubRegion *subReg = dyn_cast(region)) { + offset = getValue(offset, svalBuilder); if (!offset.isUnknownOrUndef()) return RegionRawOffsetV2(subReg, offset); + } return RegionRawOffsetV2(); } case MemRegion::ElementRegionKind: { diff --git a/test/Analysis/out-of-bounds.c b/test/Analysis/out-of-bounds.c index d6eca06571..8c65b478f1 100644 --- a/test/Analysis/out-of-bounds.c +++ b/test/Analysis/out-of-bounds.c @@ -146,3 +146,12 @@ void test4(int x) { if (x > 99) buf[x] = 1; } + +// Don't warn when indexing below the start of a symbolic region's whose +// base extent we don't know. +int *get_symbolic(); +void test_index_below_symboloc() { + int *buf = get_symbolic(); + buf[-1] = 0; // no-warning; +} +