]> granicus.if.org Git - clang/commitdiff
[analyzer] Make sure Containers OutOfBounds checker does not crash on undefined argum...
authorAnna Zaks <ganna@apple.com>
Sat, 4 Feb 2012 06:40:52 +0000 (06:40 +0000)
committerAnna Zaks <ganna@apple.com>
Sat, 4 Feb 2012 06:40:52 +0000 (06:40 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149771 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
test/Analysis/CFContainers.mm

index 2a677bc3dd08acfbe26a18a97e7830a3206f4ad3..0b16b87be3b4556ebb8a67586ea48873f0f14749 100644 (file)
@@ -56,18 +56,8 @@ public:
 };
 } // end anonymous namespace
 
-// Array state stores the array size on creation (allocation).
-// Size might be an unsigned or a symbol.
-struct ArraySize {
-  SVal NLSize;
-  ArraySize(SVal s) : NLSize(s) {}
-  void Profile(llvm::FoldingSetNodeID &ID) const {
-    NLSize.Profile(ID);
-  }
-};
-
 // ProgramState trait - a map from array symbol to it's state.
-typedef llvm::ImmutableMap<SymbolRef, SVal> ArraySizeM;
+typedef llvm::ImmutableMap<SymbolRef, DefinedSVal> ArraySizeM;
 
 namespace { struct ArraySizeMap {}; }
 namespace clang { namespace ento {
@@ -91,18 +81,20 @@ void ObjCContainersChecker::addSizeInfo(const Expr *Array, const Expr *Size,
   if (!ArraySym)
     return;
 
-  C.addTransition(State->set<ArraySizeMap>(ArraySym, SizeV));
+  C.addTransition(State->set<ArraySizeMap>(ArraySym, cast<DefinedSVal>(SizeV)));
   return;
 }
 
 void ObjCContainersChecker::checkPostStmt(const CallExpr *CE,
                                           CheckerContext &C) const {
   StringRef Name = C.getCalleeName(CE);
-  if (Name.empty())
+  if (Name.empty() || CE->getNumArgs() < 1)
     return;
 
   // Add array size information to the state.
   if (Name.equals("CFArrayCreate")) {
+    if (CE->getNumArgs() < 3)
+      return;
     // Note, we can visit the Create method in the post-visit because
     // the CFIndex parameter is passed in by value and will not be invalidated
     // by the call.
@@ -119,7 +111,7 @@ void ObjCContainersChecker::checkPostStmt(const CallExpr *CE,
 void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
                                          CheckerContext &C) const {
   StringRef Name = C.getCalleeName(CE);
-  if (Name.empty())
+  if (Name.empty() || CE->getNumArgs() < 2)
     return;
 
   // Check the array access.
@@ -128,20 +120,22 @@ void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
     // Retrieve the size.
     // Find out if we saw this array symbol before and have information about it.
     const Expr *ArrayExpr = CE->getArg(0);
-    const SVal *SizeVal = State->get<ArraySizeMap>(getArraySym(ArrayExpr, C));
-    if (!SizeVal)
+    const DefinedSVal *Size =
+                            State->get<ArraySizeMap>(getArraySym(ArrayExpr, C));
+    if (!Size)
       return;
-    DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(*SizeVal);
 
     // Get the index.
     const Expr *IdxExpr = CE->getArg(1);
     SVal IdxVal = State->getSVal(IdxExpr, C.getLocationContext());
-    DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(IdxVal);
+    if (IdxVal.isUnknownOrUndef())
+      return;
+    DefinedSVal Idx = cast<DefinedSVal>(IdxVal);
     
     // Now, check if 'Idx in [0, Size-1]'.
     const QualType T = IdxExpr->getType();
-    ProgramStateRef StInBound = State->assumeInBound(Idx, Size, true, T);
-    ProgramStateRef StOutBound = State->assumeInBound(Idx, Size, false, T);
+    ProgramStateRef StInBound = State->assumeInBound(Idx, *Size, true, T);
+    ProgramStateRef StOutBound = State->assumeInBound(Idx, *Size, false, T);
     if (StOutBound && !StInBound) {
       ExplodedNode *N = C.generateSink(StOutBound);
       if (!N)
index 4912054882ebc04d74480a801f85059d1ebc2569..e8166eba8dc8271fdc4d22decfeea35e936e688e 100644 (file)
@@ -158,7 +158,7 @@ void OutOfBoundsZiro(const void ** input, CFIndex S) {
   const void *s1 = CFArrayGetValueAtIndex(array, 0); // expected-warning {{Index is out of bounds}}
 }
 
-void TestGetCount(CFArrayRef A, CFIndex sIndex, CFIndex badIndex) {
+void TestGetCount(CFArrayRef A, CFIndex sIndex) {
   CFIndex sCount = CFArrayGetCount(A);
   if (sCount > sIndex)
     const void *s1 = CFArrayGetValueAtIndex(A, sIndex);
@@ -183,3 +183,18 @@ void TestPointerToArray(int *elems, void *p1, void *p2, void *p3, unsigned count
   CFArrayCreate(0, (const void **) &cc, count, 0); // expected-warning {{The first argument to 'CFArrayCreate' must be a C array of pointer-sized}}
   CFArrayCreate(0, (const void **) cc, count, 0); // expected-warning {{The first argument to 'CFArrayCreate' must be a C array of pointer-sized}}
 }
+
+void TestUndef(CFArrayRef A, CFIndex sIndex, void* x[]) {
+  unsigned undefVal;
+  const void *s1 = CFArrayGetValueAtIndex(A, undefVal);
+
+  unsigned undefVal2;
+  CFArrayRef B = CFArrayCreate(0, (const void **) &x, undefVal2, 0); 
+  const void *s2 = CFArrayGetValueAtIndex(B, 2);
+}
+
+void TestConst(CFArrayRef A, CFIndex sIndex, void* x[]) {
+  CFArrayRef B = CFArrayCreate(0, (const void **) &x, 4, 0); 
+  const void *s1 = CFArrayGetValueAtIndex(B, 2);
+
+}