From 459d5f62c29ee20f5e1df1a3d92c7fde1cdb2724 Mon Sep 17 00:00:00 2001 From: Jordy Rose Date: Mon, 14 May 2012 17:58:35 +0000 Subject: [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 --- clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp') 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(svalBuilder.makeIntVal(1, sizeTy)); maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Sub, *lenValNL, one, sizeTy); -- cgit v1.2.3