]> granicus.if.org Git - clang/commitdiff
static analyzer: Handle casts from arrays to integers. This fixes PR 3297.
authorTed Kremenek <kremenek@apple.com>
Tue, 13 Jan 2009 01:04:21 +0000 (01:04 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 13 Jan 2009 01:04:21 +0000 (01:04 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62130 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/PathSensitive/GRExprEngine.h
lib/Analysis/GRExprEngine.cpp
test/Analysis/null-deref-ps.c

index f7f228cfcca2481cb30547047f6a0bbed9996e8a..e62a75b8737d74e5925099836ee36da84d134912 100644 (file)
@@ -542,6 +542,11 @@ protected:
   
   /// VisitCast - Transfer function logic for all casts (implicit and explicit).
   void VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst);
+
+  /// VisitCastPointerToInteger - Transfer function (called by VisitCast) that
+  ///  handles pointer to integer casts and array to integer casts.
+  void VisitCastPointerToInteger(SVal V, const GRState* state, QualType PtrTy,
+                                 Expr* CastE, NodeTy* Pred, NodeSet& Dst);
   
   /// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
   void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, NodeTy* Pred,
index 1487ed6f2ca82465b204b38be1909901a7d1ee61..73df09a6f4aa7dca95d197cbb912ea5c3ef6f185 100644 (file)
@@ -1668,6 +1668,22 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
 // Transfer functions: Miscellaneous statements.
 //===----------------------------------------------------------------------===//
 
+void GRExprEngine::VisitCastPointerToInteger(SVal V, const GRState* state,
+                                             QualType PtrTy,
+                                             Expr* CastE, NodeTy* Pred,
+                                             NodeSet& Dst) {
+  if (!V.isUnknownOrUndef()) {
+    // FIXME: Determine if the number of bits of the target type is 
+    // equal or exceeds the number of bits to store the pointer value.
+    // If not, flag an error.
+    unsigned bits = getContext().getTypeSize(PtrTy);  
+    V = nonloc::LocAsInteger::Make(getBasicVals(), cast<Loc>(V), bits);
+  }
+  
+  MakeNode(Dst, CastE, Pred, BindExpr(state, CastE, V));
+}
+
+  
 void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
   NodeSet S1;
   QualType T = CastE->getType();
@@ -1724,14 +1740,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
   
     // Check for casts from pointers to integers.
     if (T->isIntegerType() && Loc::IsLocType(ExTy)) {
-      unsigned bits = getContext().getTypeSize(ExTy);
-    
-      // FIXME: Determine if the number of bits of the target type is 
-      // equal or exceeds the number of bits to store the pointer value.
-      // If not, flag an error.
-      
-      V = nonloc::LocAsInteger::Make(getBasicVals(), cast<Loc>(V), bits);
-      MakeNode(Dst, CastE, N, BindExpr(St, CastE, V));
+      VisitCastPointerToInteger(V, St, ExTy, CastE, N, Dst);
       continue;
     }
     
@@ -1744,11 +1753,24 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
         continue;
       }
 
-    // Check for casts from array type to pointer type.
+    // Check for casts from array type to another type.
     if (ExTy->isArrayType()) {
-      assert(T->isPointerType());
+      // We will always decay to a pointer.
       V = StateMgr.ArrayToPointer(V);
-      MakeNode(Dst, CastE, N, BindExpr(St, CastE, V));
+      
+      // Are we casting from an array to a pointer?  If so just pass on
+      // the decayed value.
+      if (T->isPointerType()) {
+        MakeNode(Dst, CastE, N, BindExpr(St, CastE, V));
+        continue;
+      }
+      
+      // Are we casting from an array to an integer?  If so, cast the decayed
+      // pointer value to an integer.
+      assert(T->isIntegerType());
+      QualType ElemTy = cast<ArrayType>(ExTy)->getElementType();
+      QualType PointerTy = getContext().getPointerType(ElemTy);
+      VisitCastPointerToInteger(V, St, PointerTy, CastE, N, Dst);
       continue;
     }
 
index 028eaabc4925b3293b3ac9813cdac5a9ef669667..e0dddc8a59b48346e3cd9a9484b3e7b522ca1057 100644 (file)
@@ -52,6 +52,27 @@ int f4(int *p) {
   return *q; // expected-warning{{Dereference of null pointer.}}
 }
 
+int f4_b() {
+  short array[2];
+  uintptr_t x = array; // expected-warning{{incompatible pointer to integer conversion initializing}}
+  short *p = x; // expected-warning{{incompatible integer to pointer conversion initializing}}
+  
+  // The following branch should be infeasible.
+  if (!(p = &array[0])) {
+    p = 0;
+    *p = 1; // no-warning
+  }
+  
+  if (p) {
+    *p = 5; // no-warning
+    p = 0;
+  }
+  else return;
+
+  *p += 10; // expected-warning{{Dereference of null pointer}}
+}
+
+
 int f5() {
   
   char *s = "hello world";