[cfe-commits] r156769 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/CStringChecker.cpp test/Analysis/string.c

Jordy Rose jediknil at belkadan.com
Mon May 14 10:58:36 PDT 2012


Author: jrose
Date: Mon May 14 12:58:35 2012
New Revision: 156769

URL: http://llvm.org/viewvc/llvm-project?rev=156769&view=rev
Log:
[analyzer] strncpy: Special-case a length of 0 to avoid an incorrect warning.

We check the address of the last element accessed, but with 0 calculating that
address results in element -1. This patch bails out early (and avoids a bunch
of other work at that).

Fixes PR12807.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
    cfe/trunk/test/Analysis/string.c

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp?rev=156769&r1=156768&r2=156769&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp Mon May 14 12:58:35 2012
@@ -1404,6 +1404,24 @@
         // For strncpy, this is just checking that lenVal <= sizeof(dst)
         // (Yes, strncpy and strncat differ in how they treat termination.
         // strncat ALWAYS terminates, but strncpy doesn't.)
+
+        // We need a special case for when the copy size is zero, in which
+        // case strncpy will do no work at all. Our bounds check uses n-1
+        // as the last element accessed, so n == 0 is problematic.
+        ProgramStateRef StateZeroSize, StateNonZeroSize;
+        llvm::tie(StateZeroSize, StateNonZeroSize) =
+          assumeZero(C, state, *lenValNL, sizeTy);
+
+        // If the size is known to be zero, we're done.
+        if (StateZeroSize && !StateNonZeroSize) {
+          StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal);
+          C.addTransition(StateZeroSize);
+          return;
+        }
+
+        // Otherwise, go ahead and figure out the last element we'll touch.
+        // We don't record the non-zero assumption here because we can't
+        // be sure. We won't warn on a possible zero.
         NonLoc one = cast<NonLoc>(svalBuilder.makeIntVal(1, sizeTy));
         maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Sub, *lenValNL,
                                                       one, sizeTy);

Modified: cfe/trunk/test/Analysis/string.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/string.c?rev=156769&r1=156768&r2=156769&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/string.c (original)
+++ cfe/trunk/test/Analysis/string.c Mon May 14 12:58:35 2012
@@ -578,6 +578,17 @@
 		(void)*(int*)0; // no-warning
 }
 
+void strncpy_zero(char *src) {
+  char dst[] = "123";
+  strncpy(dst, src, 0); // no-warning
+}
+
+void strncpy_empty() {
+  char dst[] = "123";
+  char src[] = "";
+  strncpy(dst, src, 4); // no-warning
+}
+
 //===----------------------------------------------------------------------===
 // strncat()
 //===----------------------------------------------------------------------===
@@ -716,6 +727,17 @@
   strncat(dst, src, 2); // expected-warning{{This expression will create a string whose length is too big to be represented as a size_t}}
 }
 
+void strncat_zero(char *src) {
+  char dst[] = "123";
+  strncat(dst, src, 0); // no-warning
+}
+
+void strncat_empty() {
+  char dst[8] = "123";
+  char src[] = "";
+  strncat(dst, src, 4); // no-warning
+}
+
 //===----------------------------------------------------------------------===
 // strcmp()
 //===----------------------------------------------------------------------===





More information about the cfe-commits mailing list