]> granicus.if.org Git - clang/commitdiff
Add basic support for pointer arithmetic in
authorTed Kremenek <kremenek@apple.com>
Fri, 24 Dec 2010 08:39:33 +0000 (08:39 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 24 Dec 2010 08:39:33 +0000 (08:39 +0000)
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

include/clang/StaticAnalyzer/PathSensitive/MemRegion.h
include/clang/StaticAnalyzer/PathSensitive/Store.h
lib/StaticAnalyzer/Checkers/ExprEngine.cpp
lib/StaticAnalyzer/SimpleSValBuilder.cpp
test/Analysis/out-of-bounds.c

index 33779a9fd5276051e6f24a70bd647bcd737e6ed6..6ba3dc68fcf7254afc0973ebe4eb8791eed139f2 100644 (file)
@@ -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 {
index c48f129febee868b99696380fac58ca362e188be..7054d64a38978248363d29b6584467a3212fbe58 100644 (file)
@@ -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;
index 17bc339f7548e1c099d6c27ab6af0b6bcf6c3df0..c522e72210feef2765454eee41e761ad201cdc08 100644 (file)
@@ -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());
 
index f1a9074b952dc5a29682c6a9758948bfd88c07ed..a6432121f5441423406e99e1aeeb3dc0983371c3 100644 (file)
@@ -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,
index 598e1653763639bb23cd6603fbd2814804e65e99..d8e4ad915a056e3609ff2ee7590d256284974f0b 100644 (file)
@@ -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: