Hi krememek, zaks.anna, jordan_rose,

Enable static analyzer to throw warnings when uninitialized source array of 
known length is given as the argument to strcpy function, where dest size < 
source size.
char x[3] = "abc";
char y[4];
strcpy(x,y); // emit buffer overflow warning

http://reviews.llvm.org/D6012

Files:
  lib/StaticAnalyzer/Checkers/CStringChecker.cpp
  test/Analysis/string.c
Index: test/Analysis/string.c
===================================================================
--- test/Analysis/string.c
+++ test/Analysis/string.c
@@ -303,6 +303,24 @@
     strcpy(x, y); // no-warning
 }
 
+void strcpy_src_uninit_overflow1() {
+  char x[3] = "abc";
+  char y[4];
+  strcpy(x,y);  // expected-warning{{String copy function overflows destination buffer}}
+}
+
+void strcpy_src_uninit_overflow2() {
+  char x[3] = "abc";
+  char y[3];
+  strcpy(x,y);  // no-warning
+}
+
+void strcpy_src_uninit_overflow3() {
+  char x[3] = "abc";
+  char y[2];
+  strcpy(x,y);  // no-warning
+}
+
 //===----------------------------------------------------------------------===
 // stpcpy()
 //===----------------------------------------------------------------------===
Index: lib/StaticAnalyzer/Checkers/CStringChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -39,6 +39,7 @@
       BT_NotCString, BT_AdditionOverflow;
 
   mutable const char *CurrentFunctionDescription;
+  static bool isSrcUninit;
 
 public:
   /// The filter is used to filter out the diagnostics which are not enabled by
@@ -195,6 +196,8 @@
                                             NonLoc right) const;
 };
 
+bool CStringChecker::isSrcUninit = 0;
+
 } //end anonymous namespace
 
 REGISTER_MAP_WITH_PROGRAMSTATE(CStringLength, const MemRegion *, SVal)
@@ -667,6 +670,12 @@
     const SVal *Recorded = state->get<CStringLength>(MR);
     if (Recorded)
       return *Recorded;
+    else {
+	// set isSrcUninit, so that we will try to evaluate size of src for strcpy fn
+	// if we cannot calculate size in strcpy function
+	// we will use the symbolic value generated after this.
+	isSrcUninit = 1;
+	} 
   }
 
   // Otherwise, get a new symbol and update the state.
@@ -1360,6 +1369,35 @@
   QualType cmpTy = svalBuilder.getConditionType();
   QualType sizeTy = svalBuilder.getContext().getSizeType();
 
+  // If we could not record proper string length, try to get the size of src buffer
+  if (isSrcUninit && !isAppending && !isBounded && !returnEnd) {
+    isSrcUninit = 0;
+    const MemRegion *R = srcVal.getAsRegion();
+    if (!R)
+      return;
+
+    const ElementRegion *ER = dyn_cast<ElementRegion>(R);
+    SVal retsize = UnknownVal();
+    if (ER) {
+      assert(ER->getValueType() == C.getASTContext().CharTy &&
+      "Should only be called with char* ElementRegions");
+
+      // Get the size of the array.
+      const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
+      SVal Extent = svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
+      DefinedOrUnknownSVal strSize = cast<DefinedOrUnknownSVal>(Extent);
+      retsize = strSize;
+
+      NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
+      NonLoc *knownStrSize = cast<NonLoc>(&retsize);
+      retsize = (svalBuilder.evalBinOpNN(state, BO_Sub, *knownStrSize, One, sizeTy));
+
+      if (!(retsize.isUnknown()) && !(retsize.isUndef())) {
+        strLength = retsize;
+      }
+    }
+  }
+
   // These two values allow checking two kinds of errors:
   // - actual overflows caused by a source that doesn't fit in the destination
   // - potential overflows caused by a bound that could exceed the destination
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to