[cfe-commits] r60726 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRExprEngine.h lib/Analysis/GRExprEngine.cpp lib/Analysis/GRExprEngineInternalChecks.cpp

Ted Kremenek kremenek at apple.com
Mon Dec 8 14:47:34 PST 2008


Author: kremenek
Date: Mon Dec  8 16:47:34 2008
New Revision: 60726

URL: http://llvm.org/viewvc/llvm-project?rev=60726&view=rev
Log:
Add checking for zero-sized VLAs.

Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
    cfe/trunk/lib/Analysis/GRExprEngine.cpp
    cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h?rev=60726&r1=60725&r2=60726&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Mon Dec  8 16:47:34 2008
@@ -94,74 +94,70 @@
   llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor;
   
 public:
-  typedef llvm::SmallPtrSet<NodeTy*,2> UndefBranchesTy;  
-  typedef llvm::SmallPtrSet<NodeTy*,2> UndefStoresTy;
-  typedef llvm::SmallPtrSet<NodeTy*,2> BadDerefTy;
-  typedef llvm::SmallPtrSet<NodeTy*,2> BadCallsTy;
-  typedef llvm::SmallPtrSet<NodeTy*,2> UndefReceiversTy;
+  typedef llvm::SmallPtrSet<NodeTy*,2> ErrorNodes;  
   typedef llvm::DenseMap<NodeTy*, Expr*> UndefArgsTy;
-  typedef llvm::SmallPtrSet<NodeTy*,2> BadDividesTy;
-  typedef llvm::SmallPtrSet<NodeTy*,2> NoReturnCallsTy;  
-  typedef llvm::SmallPtrSet<NodeTy*,2> UndefResultsTy;
-  typedef llvm::SmallPtrSet<NodeTy*,2> RetsStackAddrTy;
-  typedef llvm::SmallPtrSet<NodeTy*,2> RetsUndefTy;
-  typedef llvm::SmallPtrSet<NodeTy*,2> OutOfBoundMemAccessesTy;
   
-protected:
-
   /// RetsStackAddr - Nodes in the ExplodedGraph that result from returning
   ///  the address of a stack variable.
-  RetsStackAddrTy RetsStackAddr;
+  ErrorNodes RetsStackAddr;
 
   /// RetsUndef - Nodes in the ExplodedGraph that result from returning
   ///  an undefined value.
-  RetsUndefTy RetsUndef;
+  ErrorNodes RetsUndef;
   
   /// UndefBranches - Nodes in the ExplodedGraph that result from
   ///  taking a branch based on an undefined value.
-  UndefBranchesTy UndefBranches;
+  ErrorNodes UndefBranches;
   
   /// UndefStores - Sinks in the ExplodedGraph that result from
   ///  making a store to an undefined lvalue.
-  UndefStoresTy UndefStores;
+  ErrorNodes UndefStores;
   
   /// NoReturnCalls - Sinks in the ExplodedGraph that result from
   //  calling a function with the attribute "noreturn".
-  NoReturnCallsTy NoReturnCalls;
+  ErrorNodes NoReturnCalls;
   
   /// ImplicitNullDeref - Nodes in the ExplodedGraph that result from
   ///  taking a dereference on a symbolic pointer that MAY be NULL.
-  BadDerefTy ImplicitNullDeref;
+  ErrorNodes ImplicitNullDeref;
     
   /// ExplicitNullDeref - Nodes in the ExplodedGraph that result from
   ///  taking a dereference on a symbolic pointer that MUST be NULL.
-  BadDerefTy ExplicitNullDeref;
+  ErrorNodes ExplicitNullDeref;
   
   /// UnitDeref - Nodes in the ExplodedGraph that result from
   ///  taking a dereference on an undefined value.
-  BadDerefTy UndefDeref;
+  ErrorNodes UndefDeref;
 
   /// ImplicitBadDivides - Nodes in the ExplodedGraph that result from 
   ///  evaluating a divide or modulo operation where the denominator
   ///  MAY be zero.
-  BadDividesTy ImplicitBadDivides;
+  ErrorNodes ImplicitBadDivides;
   
   /// ExplicitBadDivides - Nodes in the ExplodedGraph that result from 
   ///  evaluating a divide or modulo operation where the denominator
   ///  MUST be zero or undefined.
-  BadDividesTy ExplicitBadDivides;
+  ErrorNodes ExplicitBadDivides;
+  
+  /// ImplicitZeroSizedVLA - Nodes in the ExplodedGraph that result from 
+  ///  constructing a zero-sized VLA where the size may be zero.
+  ErrorNodes ImplicitZeroSizedVLA;
+  
+  /// ExplicitZeroSizedVLA - Nodes in the ExplodedGraph that result from 
+  ///  constructing a zero-sized VLA where the size must be zero.
+  ErrorNodes ExplicitZeroSizedVLA;
   
   /// UndefResults - Nodes in the ExplodedGraph where the operands are defined
   ///  by the result is not.  Excludes divide-by-zero errors.
-  UndefResultsTy UndefResults;
+  ErrorNodes UndefResults;
   
   /// BadCalls - Nodes in the ExplodedGraph resulting from calls to function
   ///  pointers that are NULL (or other constants) or Undefined.
-  BadCallsTy BadCalls;
+  ErrorNodes BadCalls;
   
   /// UndefReceiver - Nodes in the ExplodedGraph resulting from message
   ///  ObjC message expressions where the receiver is undefined (uninitialized).
-  UndefReceiversTy UndefReceivers;
+  ErrorNodes UndefReceivers;
   
   /// UndefArg - Nodes in the ExplodedGraph resulting from calls to functions
   ///   where a pass-by-value argument has an undefined value.
@@ -174,11 +170,11 @@
 
   /// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from
   /// out-of-bound memory accesses where the index MAY be out-of-bound.
-  OutOfBoundMemAccessesTy ImplicitOOBMemAccesses;
+  ErrorNodes ImplicitOOBMemAccesses;
 
   /// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from
   /// out-of-bound memory accesses where the index MUST be out-of-bound.
-  OutOfBoundMemAccessesTy ExplicitOOBMemAccesses;
+  ErrorNodes ExplicitOOBMemAccesses;
   
 public:
   GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx, LiveVariables& L,
@@ -298,19 +294,19 @@
     return N->isSink() && UndefReceivers.count(const_cast<NodeTy*>(N)) != 0;
   }
   
-  typedef RetsStackAddrTy::iterator ret_stackaddr_iterator;
+  typedef ErrorNodes::iterator ret_stackaddr_iterator;
   ret_stackaddr_iterator ret_stackaddr_begin() { return RetsStackAddr.begin(); }
   ret_stackaddr_iterator ret_stackaddr_end() { return RetsStackAddr.end(); }  
   
-  typedef RetsUndefTy::iterator ret_undef_iterator;
+  typedef ErrorNodes::iterator ret_undef_iterator;
   ret_undef_iterator ret_undef_begin() { return RetsUndef.begin(); }
   ret_undef_iterator ret_undef_end() { return RetsUndef.end(); }
   
-  typedef UndefBranchesTy::iterator undef_branch_iterator;
+  typedef ErrorNodes::iterator undef_branch_iterator;
   undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); }
   undef_branch_iterator undef_branches_end() { return UndefBranches.end(); }  
   
-  typedef BadDerefTy::iterator null_deref_iterator;
+  typedef ErrorNodes::iterator null_deref_iterator;
   null_deref_iterator null_derefs_begin() { return ExplicitNullDeref.begin(); }
   null_deref_iterator null_derefs_end() { return ExplicitNullDeref.end(); }
   
@@ -321,11 +317,11 @@
     return ImplicitNullDeref.end();
   }
   
-  typedef BadDerefTy::iterator undef_deref_iterator;
+  typedef ErrorNodes::iterator undef_deref_iterator;
   undef_deref_iterator undef_derefs_begin() { return UndefDeref.begin(); }
   undef_deref_iterator undef_derefs_end() { return UndefDeref.end(); }
   
-  typedef BadDividesTy::iterator bad_divide_iterator;
+  typedef ErrorNodes::iterator bad_divide_iterator;
 
   bad_divide_iterator explicit_bad_divides_begin() {
     return ExplicitBadDivides.begin();
@@ -343,11 +339,11 @@
     return ImplicitBadDivides.end();
   }
   
-  typedef UndefResultsTy::iterator undef_result_iterator;
+  typedef ErrorNodes::iterator undef_result_iterator;
   undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
   undef_result_iterator undef_results_end() { return UndefResults.end(); }
 
-  typedef BadCallsTy::iterator bad_calls_iterator;
+  typedef ErrorNodes::iterator bad_calls_iterator;
   bad_calls_iterator bad_calls_begin() { return BadCalls.begin(); }
   bad_calls_iterator bad_calls_end() { return BadCalls.end(); }  
   
@@ -362,7 +358,7 @@
     return MsgExprUndefArgs.end();
   }  
   
-  typedef UndefReceiversTy::iterator undef_receivers_iterator;
+  typedef ErrorNodes::iterator undef_receivers_iterator;
 
   undef_receivers_iterator undef_receivers_begin() {
     return UndefReceivers.begin();
@@ -372,7 +368,7 @@
     return UndefReceivers.end();
   }
 
-  typedef OutOfBoundMemAccessesTy::iterator oob_memacc_iterator;
+  typedef ErrorNodes::iterator oob_memacc_iterator;
   oob_memacc_iterator implicit_oob_memacc_begin() { 
     return ImplicitOOBMemAccesses.begin();
   }

Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=60726&r1=60725&r2=60726&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Mon Dec  8 16:47:34 2008
@@ -1773,8 +1773,7 @@
   if (!D || !isa<VarDecl>(D))
     return;
   
-  const VarDecl* VD = dyn_cast<VarDecl>(D);
-  
+  const VarDecl* VD = dyn_cast<VarDecl>(D);    
   Expr* InitEx = const_cast<Expr*>(VD->getInit());
 
   // FIXME: static variables may have an initializer, but the second
@@ -1812,6 +1811,33 @@
     }
     else
       St = StateMgr.BindDecl(St, VD, 0, Count);
+    
+    
+    // Check if 'VD' is a VLA and if so check if has a non-zero size.
+    QualType T = getContext().getCanonicalType(VD->getType());
+    if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
+      // FIXME: Handle multi-dimensional VLAs.
+      
+      Expr* SE = VLA->getSizeExpr();
+      SVal Size = GetSVal(St, SE);
+
+      bool isFeasibleZero = false;
+      const GRState* ZeroSt =  Assume(St, Size, false, isFeasibleZero);
+            
+      bool isFeasibleNotZero = false;
+      St = Assume(St, Size, true, isFeasibleNotZero);
+      
+      if (isFeasibleZero) {
+        if (NodeTy* N = Builder->generateNode(DS, ZeroSt, Pred)) {
+          N->markAsSink();          
+          if (isFeasibleNotZero) ImplicitZeroSizedVLA.insert(N);
+          else ExplicitZeroSizedVLA.insert(N);
+        }
+      }
+      
+      if (!isFeasibleNotZero)
+        continue;      
+    }
 
     MakeNode(Dst, DS, *I, St);
   }

Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp?rev=60726&r1=60725&r2=60726&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp Mon Dec  8 16:47:34 2008
@@ -163,7 +163,7 @@
                "Receiver in message expression is an uninitialized value.") {}
   
   virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
-    for (GRExprEngine::UndefReceiversTy::iterator I=Eng.undef_receivers_begin(),
+    for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
          End = Eng.undef_receivers_end(); I!=End; ++I) {
       
       // Generate a report for this bug.
@@ -331,6 +331,33 @@
     Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
   }
 };
+  
+class VISIBILITY_HIDDEN ZeroSizeVLA : public BuiltinBug {
+
+public:
+  ZeroSizeVLA() : BuiltinBug("Zero-sized VLA",  
+                             "VLAs with zero-size are undefined.") {}
+  
+  virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
+    for (GRExprEngine::ErrorNodes::iterator
+          I = Eng.ExplicitZeroSizedVLA.begin(),
+          E = Eng.ExplicitZeroSizedVLA.end(); I!=E; ++I) {
+      
+      // Generate a report for this bug.
+      PostStmt PS = cast<PostStmt>((*I)->getLocation());      
+      DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
+      VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
+      QualType T = Eng.getContext().getCanonicalType(VD->getType());
+      VariableArrayType* VT = cast<VariableArrayType>(T);
+      
+      RangedBugReport report(*this, *I);
+      report.addRange(VT->getSizeExpr()->getSourceRange());
+      
+      // Emit the warning.
+      BR.EmitWarning(report);
+    }
+  }
+};
 
 //===----------------------------------------------------------------------===//
 // __attribute__(nonnull) checking
@@ -403,5 +430,6 @@
   Register(new BadMsgExprArg());
   Register(new BadReceiver());
   Register(new OutOfBoundMemoryAccess());
+  Register(new ZeroSizeVLA());
   AddCheck(new CheckAttrNonNull(), Stmt::CallExprClass); 
 }





More information about the cfe-commits mailing list