diff options
author | Jordy Rose <jediknil@belkadan.com> | 2012-05-14 17:58:35 +0000 |
---|---|---|
committer | Jordy Rose <jediknil@belkadan.com> | 2012-05-14 17:58:35 +0000 |
commit | 459d5f62c29ee20f5e1df1a3d92c7fde1cdb2724 (patch) | |
tree | 1a206f89a8d819a3f8025fa6cdfbefb610069a38 /clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp | |
parent | 77e7b8ede2b87b0be45bc034c0bdde5e299452e9 (diff) | |
download | bcm5719-llvm-459d5f62c29ee20f5e1df1a3d92c7fde1cdb2724.tar.gz bcm5719-llvm-459d5f62c29ee20f5e1df1a3d92c7fde1cdb2724.zip |
[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.
llvm-svn: 156769
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index bd1a56a1aa0..942280d03d2 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/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); |