]> granicus.if.org Git - clang/commitdiff
Add support for computing size in elements for symbolic regions obtained from
authorZhongxing Xu <xuzhongxing@gmail.com>
Mon, 18 Jan 2010 08:54:31 +0000 (08:54 +0000)
committerZhongxing Xu <xuzhongxing@gmail.com>
Mon, 18 Jan 2010 08:54:31 +0000 (08:54 +0000)
malloc().

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93722 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/PathSensitive/Store.h
lib/Analysis/ArrayBoundChecker.cpp
lib/Analysis/MallocChecker.cpp
lib/Analysis/RegionStore.cpp
lib/Analysis/ReturnPointerRangeChecker.cpp
test/Analysis/outofbound.c

index 70c17accb72587c6f4d0b9cb0f606bf667e8ec2b..5606df0014f0ee500bbd4a9b1d1d826258b6caaf 100644 (file)
@@ -105,7 +105,8 @@ public:
 
   // FIXME: Make out-of-line.
   virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state, 
-                                                 const MemRegion *region) {
+                                                 const MemRegion *region,
+                                                 QualType EleTy) {
     return UnknownVal();
   }
 
index 3d95ab183471b51e972eac99a48b24f683eb3a6d..49c86068265b16bcaef817e9bb3818e94ae26a01 100644 (file)
@@ -57,7 +57,8 @@ void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){
 
   // Get the size of the array.
   DefinedOrUnknownSVal NumElements 
-    = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion());
+    = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(), 
+                                         ER->getValueType(C.getASTContext()));
 
   const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
   const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
index 5bd27912e41f479856c1a719449550f5d6fd6938..28f4db78806827c8c7e1c7d17dd733b6dae85e82 100644 (file)
@@ -72,7 +72,7 @@ public:
 private:
   void MallocMem(CheckerContext &C, const CallExpr *CE);
   const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
-                              const GRState *state);
+                              const Expr *SizeEx, const GRState *state);
   void FreeMem(CheckerContext &C, const CallExpr *CE);
   const GRState *FreeMemAux(CheckerContext &C, const CallExpr *CE,
                             const GRState *state);
@@ -136,18 +136,24 @@ bool MallocChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
 }
 
 void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
-  const GRState *state = MallocMemAux(C, CE, C.getState());
+  const GRState *state = MallocMemAux(C, CE, CE->getArg(0), C.getState());
   C.addTransition(state);
 }
 
 const GRState *MallocChecker::MallocMemAux(CheckerContext &C,  
                                            const CallExpr *CE,
+                                           const Expr *SizeEx,
                                            const GRState *state) {
   unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
   ValueManager &ValMgr = C.getValueManager();
 
   SVal RetVal = ValMgr.getConjuredSymbolVal(NULL, CE, CE->getType(), Count);
 
+  SVal Size = state->getSVal(SizeEx);
+
+  state = C.getEngine().getStoreManager().setExtent(state, RetVal.getAsRegion(),
+                                                    Size);
+
   state = state->BindExpr(CE, RetVal);
   
   SymbolRef Sym = RetVal.getAsLocSymbol();
@@ -216,7 +222,7 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) {
     if (Sym)
       stateEqual = stateEqual->set<RegionState>(Sym, RefState::getReleased(CE));
 
-    const GRState *stateMalloc = MallocMemAux(C, CE, stateEqual);
+    const GRState *stateMalloc = MallocMemAux(C, CE, CE->getArg(1), stateEqual);
     C.addTransition(stateMalloc);
   }
 
@@ -237,7 +243,8 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) {
       const GRState *stateFree = FreeMemAux(C, CE, stateSizeNotZero);
       if (stateFree) {
         // FIXME: We should copy the content of the original buffer.
-        const GRState *stateRealloc = MallocMemAux(C, CE, stateFree);
+        const GRState *stateRealloc = MallocMemAux(C, CE, CE->getArg(1), 
+                                                   stateFree);
         C.addTransition(stateRealloc);
       }
     }
index 9b5b44be64273489a32439a06e36268262280559..a735ed94578e7d3b9c5011824549da2fcd3f2704 100644 (file)
@@ -21,6 +21,7 @@
 #include "clang/Analysis/Analyses/LiveVariables.h"
 #include "clang/Analysis/Support/Optional.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/AST/CharUnits.h"
 
 #include "llvm/ADT/ImmutableMap.h"
 #include "llvm/ADT/ImmutableList.h"
@@ -423,9 +424,9 @@ public:
   // Region "extents".
   //===------------------------------------------------------------------===//
 
-  const GRState *setExtent(const GRState *state, const MemRegion* R, SVal Extent);
+  const GRState *setExtent(const GRState *state,const MemRegion* R,SVal Extent);
   DefinedOrUnknownSVal getSizeInElements(const GRState *state, 
-                                         const MemRegion* R);
+                                         const MemRegion* R, QualType EleTy);
 
   //===------------------------------------------------------------------===//
   // Utility methods.
@@ -767,7 +768,8 @@ SVal RegionStoreManager::getLValueElement(QualType elementType, SVal Offset,
 //===----------------------------------------------------------------------===//
 
 DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
-                                                           const MemRegion *R) {
+                                                           const MemRegion *R,
+                                                           QualType EleTy) {
 
   switch (R->getKind()) {
     case MemRegion::CXXThisRegionKind:
@@ -793,10 +795,25 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
     case MemRegion::ElementRegionKind:
     case MemRegion::FieldRegionKind:
     case MemRegion::ObjCIvarRegionKind:
-    case MemRegion::SymbolicRegionKind:
     case MemRegion::CXXObjectRegionKind:
       return UnknownVal();
 
+    case MemRegion::SymbolicRegionKind: {
+      const SVal *Size = state->get<RegionExtents>(R);
+      if (!Size)
+        return UnknownVal();
+      const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(Size);
+      if (!CI)
+        return UnknownVal();
+
+      CharUnits RegionSize = 
+        CharUnits::fromQuantity(CI->getValue().getSExtValue());
+      CharUnits EleSize = getContext().getTypeSizeInChars(EleTy);
+      assert(RegionSize % EleSize == 0);
+
+      return ValMgr.makeIntVal(RegionSize / EleSize, false);
+    }
+
     case MemRegion::StringRegionKind: {
       const StringLiteral* Str = cast<StringRegion>(R)->getStringLiteral();
       // We intentionally made the size value signed because it participates in
index ab0fcab4219ed56c33d0b54f43b7cbc284c3d91c..b0350cb576ff09d441c10b4daf595ae316376d80 100644 (file)
@@ -65,7 +65,8 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
   // into a common place.
 
   DefinedOrUnknownSVal NumElements
-    = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion());
+    = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
+                                           ER->getValueType(C.getASTContext()));
 
   const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
   const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
index 2142e9e1f73b14481a0360487159fddd615d357a..68e77caa36bd545f6bcca8be569e37567b164a72 100644 (file)
@@ -1,7 +1,15 @@
-// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-experimental-checks -checker-cfref -analyzer-store=region -verify %s
+
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
 
 char f1() {
   char* s = "abcd";
   char c = s[4]; // no-warning
   return s[5] + c; // expected-warning{{Access out-of-bound array element (buffer overflow)}}
 }
+
+void f2() {
+  int *p = malloc(12);
+  p[3] = 4; // expected-warning{{Access out-of-bound array element (buffer overflow)}}
+}