aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
diff options
context:
space:
mode:
authorJordy Rose <jediknil@belkadan.com>2012-05-14 17:58:35 +0000
committerJordy Rose <jediknil@belkadan.com>2012-05-14 17:58:35 +0000
commit6e4244ee86a2d71af4eac791808f2dc50c7484e6 (patch)
treef6019e37b66b9b3574f4a1b748df1489d8760c58 /lib/StaticAnalyzer/Checkers/CStringChecker.cpp
parent2c40835c21cd435f183da3d4754aff6beeaef9f6 (diff)
[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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156769 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/CStringChecker.cpp')
-rw-r--r--lib/StaticAnalyzer/Checkers/CStringChecker.cpp18
1 files changed, 18 insertions, 0 deletions
diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index bd1a56a1aa..942280d03d 100644
--- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -1404,6 +1404,24 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
// 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);