summaryrefslogtreecommitdiffstats
path: root/clang/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
commit459d5f62c29ee20f5e1df1a3d92c7fde1cdb2724 (patch)
tree1a206f89a8d819a3f8025fa6cdfbefb610069a38 /clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
parent77e7b8ede2b87b0be45bc034c0bdde5e299452e9 (diff)
downloadbcm5719-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.cpp18
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);
OpenPOWER on IntegriCloud