aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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: