[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