aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2010-12-24 08:39:33 +0000
committerTed Kremenek <kremenek@apple.com>2010-12-24 08:39:33 +0000
commita6b0b96e5376cd9cf182a3e240e0537feed43cde (patch)
tree99f1677f9c39c2c85dcec745008525cdac11ad62
parent3252134192221e65c937124cc79b97d3b04389ae (diff)
Add basic support for pointer arithmetic in
SimpleSValBuilder. This clears up some false positives emitted by ArrayBoundCheckerV2 due to the lack of support for pointer arithmetic. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122546 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/StaticAnalyzer/PathSensitive/MemRegion.h6
-rw-r--r--include/clang/StaticAnalyzer/PathSensitive/Store.h7
-rw-r--r--lib/StaticAnalyzer/Checkers/ExprEngine.cpp2
-rw-r--r--lib/StaticAnalyzer/SimpleSValBuilder.cpp41
-rw-r--r--test/Analysis/out-of-bounds.c10
5 files changed, 46 insertions, 20 deletions
diff --git a/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h
index 33779a9fd5..6ba3dc68fc 100644
--- a/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h
+++ b/include/clang/StaticAnalyzer/PathSensitive/MemRegion.h
@@ -357,7 +357,11 @@ public:
virtual QualType getLocationType() const {
// FIXME: We can possibly optimize this later to cache this value.
- return getContext().getPointerType(getValueType());
+ QualType T = getValueType();
+ ASTContext &ctx = getContext();
+ if (T->getAs<ObjCObjectType>())
+ return ctx.getObjCObjectPointerType(T);
+ return ctx.getPointerType(getValueType());
}
QualType getDesugaredValueType(ASTContext &Context) const {
diff --git a/include/clang/StaticAnalyzer/PathSensitive/Store.h b/include/clang/StaticAnalyzer/PathSensitive/Store.h
index c48f129feb..7054d64a38 100644
--- a/include/clang/StaticAnalyzer/PathSensitive/Store.h
+++ b/include/clang/StaticAnalyzer/PathSensitive/Store.h
@@ -153,13 +153,6 @@ public:
/// casted and 'CastToTy' the result type of the cast.
const MemRegion *CastRegion(const MemRegion *region, QualType CastToTy);
-
- /// evalBinOp - Perform pointer arithmetic.
- virtual SVal evalBinOp(BinaryOperator::Opcode Op,
- Loc lhs, NonLoc rhs, QualType resultTy) {
- return UnknownVal();
- }
-
virtual Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
diff --git a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
index 17bc339f75..c522e72210 100644
--- a/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
@@ -2950,7 +2950,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
SVal RHS;
if (U->getType()->isAnyPointerType())
- RHS = svalBuilder.makeIntValWithPtrWidth(1, false);
+ RHS = svalBuilder.makeArrayIndex(1);
else
RHS = svalBuilder.makeIntVal(1, U->getType());
diff --git a/lib/StaticAnalyzer/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/SimpleSValBuilder.cpp
index f1a9074b95..a6432121f5 100644
--- a/lib/StaticAnalyzer/SimpleSValBuilder.cpp
+++ b/lib/StaticAnalyzer/SimpleSValBuilder.cpp
@@ -808,6 +808,11 @@ SVal SimpleSValBuilder::evalBinOpLL(const GRState *state,
SVal SimpleSValBuilder::evalBinOpLN(const GRState *state,
BinaryOperator::Opcode op,
Loc lhs, NonLoc rhs, QualType resultTy) {
+
+ // Special case: rhs is a zero constant.
+ if (rhs.isZeroConstant())
+ return lhs;
+
// Special case: 'rhs' is an integer that has the same width as a pointer and
// we are using the integer location in a comparison. Normally this cannot be
// triggered, but transfer functions like those for OSCommpareAndSwapBarrier32
@@ -858,11 +863,39 @@ SVal SimpleSValBuilder::evalBinOpLN(const GRState *state,
return loc::ConcreteInt(getBasicValueFactory().getValue(rightI));
}
}
-
- // Delegate remaining pointer arithmetic to the StoreManager.
- return state->getStateManager().getStoreManager().evalBinOp(op, lhs,
- rhs, resultTy);
+ // Handle cases where 'lhs' is a region.
+ if (const MemRegion *region = lhs.getAsRegion()) {
+ rhs = cast<NonLoc>(convertToArrayIndex(rhs));
+ SVal index = UnknownVal();
+ const MemRegion *superR = 0;
+ QualType elementType;
+
+ if (const ElementRegion *elemReg = dyn_cast<ElementRegion>(region)) {
+ index = evalBinOpNN(state, BO_Add, elemReg->getIndex(), rhs,
+ getArrayIndexType());
+ superR = elemReg->getSuperRegion();
+ elementType = elemReg->getElementType();
+ }
+ else if (isa<SubRegion>(region)) {
+ superR = region;
+ index = rhs;
+ if (const PointerType *PT = resultTy->getAs<PointerType>()) {
+ elementType = PT->getPointeeType();
+ }
+ else {
+ const ObjCObjectPointerType *OT =
+ resultTy->getAs<ObjCObjectPointerType>();
+ elementType = OT->getPointeeType();
+ }
+ }
+
+ if (NonLoc *indexV = dyn_cast<NonLoc>(&index)) {
+ return loc::MemRegionVal(MemMgr.getElementRegion(elementType, *indexV,
+ superR, getContext()));
+ }
+ }
+ return UnknownVal();
}
const llvm::APSInt *SimpleSValBuilder::getKnownValue(const GRState *state,
diff --git a/test/Analysis/out-of-bounds.c b/test/Analysis/out-of-bounds.c
index 598e165376..d8e4ad915a 100644
--- a/test/Analysis/out-of-bounds.c
+++ b/test/Analysis/out-of-bounds.c
@@ -44,7 +44,6 @@ void test1_ptr_ok(int x) {
p[99] = 1; // no-warning
}
-// ** FIXME ** Doesn't work yet because we don't support pointer arithmetic.
// Tests doing an out-of-bounds access before the start of an array using:
// - indirect pointer to buffer, manipulated using simple pointer arithmetic
// - constant integer index
@@ -53,7 +52,7 @@ void test1_ptr_arith(int x) {
int buf[100];
int *p = buf;
p = p + 100;
- p[0] = 1; // no-warning
+ p[0] = 1; // expected-warning{{Out of bound memory access}}
}
void test1_ptr_arith_ok(int x) {
@@ -63,21 +62,18 @@ void test1_ptr_arith_ok(int x) {
p[0] = 1; // no-warning
}
-// ** FIXME ** Doesn't work yet because we don't support pointer arithmetic.
void test1_ptr_arith_bad(int x) {
int buf[100];
int *p = buf;
p = p + 99;
- p[1] = 1; // no-warning
+ p[1] = 1; // expected-warning{{Out of bound memory access}}
}
-// ** FIXME ** we falsely emit a warning here because of our lack of
-// handling of pointer arithmetic.
void test1_ptr_arith_ok2(int x) {
int buf[100];
int *p = buf;
p = p + 99;
- p[-1] = 1; // expected-warning{{Out of bound}}
+ p[-1] = 1; // no-warning
}
// Tests doing an out-of-bounds access before the start of an array using: