summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2011-02-22 04:58:34 +0000
committerTed Kremenek <kremenek@apple.com>2011-02-22 04:58:34 +0000
commitfb1a79af7aff4cec44a4a0d2a83bb081cf702151 (patch)
treebe41501de16cebae5966a5b669da151b437343f4 /clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
parent280a01fa1b9933dbc4e2c9a5574efd9320d37635 (diff)
downloadbcm5719-llvm-fb1a79af7aff4cec44a4a0d2a83bb081cf702151.tar.gz
bcm5719-llvm-fb1a79af7aff4cec44a4a0d2a83bb081cf702151.zip
Add CStringChecker support for strncpy. Patch by Lenny Maiorani!
llvm-svn: 126188
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp41
1 files changed, 37 insertions, 4 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index e9722a6de6b..ddeb368f2b9 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -59,8 +59,10 @@ public:
bool IsStrnlen = false);
void evalStrcpy(CheckerContext &C, const CallExpr *CE);
+ void evalStrncpy(CheckerContext &C, const CallExpr *CE);
void evalStpcpy(CheckerContext &C, const CallExpr *CE);
- void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd);
+ void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd,
+ bool isStrncpy);
// Utility methods
std::pair<const GRState*, const GRState*>
@@ -845,16 +847,21 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) {
// char *strcpy(char *restrict dst, const char *restrict src);
- evalStrcpyCommon(C, CE, /* returnEnd = */ false);
+ evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ false);
+}
+
+void CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) {
+ // char *strcpy(char *restrict dst, const char *restrict src);
+ evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ true);
}
void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) {
// char *stpcpy(char *restrict dst, const char *restrict src);
- evalStrcpyCommon(C, CE, /* returnEnd = */ true);
+ evalStrcpyCommon(C, CE, /* returnEnd = */ true, /* isStrncpy = */ false);
}
void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
- bool returnEnd) {
+ bool returnEnd, bool isStrncpy) {
const GRState *state = C.getState();
// Check that the destination is non-null
@@ -879,6 +886,31 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
if (strLength.isUndef())
return;
+ if (isStrncpy) {
+ // Get the max number of characters to copy
+ const Expr *lenExpr = CE->getArg(2);
+ SVal lenVal = state->getSVal(lenExpr);
+
+ NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength);
+ NonLoc *lenValNL = dyn_cast<NonLoc>(&lenVal);
+
+ QualType cmpTy = C.getSValBuilder().getContext().IntTy;
+ const GRState *stateTrue, *stateFalse;
+
+ // Check if the max number to copy is less than the length of the src
+ llvm::tie(stateTrue, stateFalse) =
+ state->assume(cast<DefinedOrUnknownSVal>
+ (C.getSValBuilder().evalBinOpNN(state, BO_GT,
+ *strLengthNL, *lenValNL,
+ cmpTy)));
+
+ if (stateTrue) {
+ // Max number to copy is less than the length of the src, so the actual
+ // strLength copied is the max number arg.
+ strLength = lenVal;
+ }
+ }
+
SVal Result = (returnEnd ? UnknownVal() : DstVal);
// If the destination is a MemRegion, try to check for a buffer overflow and
@@ -951,6 +983,7 @@ bool CStringChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
.Cases("memcmp", "bcmp", &CStringChecker::evalMemcmp)
.Cases("memmove", "__memmove_chk", &CStringChecker::evalMemmove)
.Cases("strcpy", "__strcpy_chk", &CStringChecker::evalStrcpy)
+ .Cases("strncpy", "__strncpy_chk", &CStringChecker::evalStrncpy)
.Cases("stpcpy", "__stpcpy_chk", &CStringChecker::evalStpcpy)
.Case("strlen", &CStringChecker::evalstrLength)
.Case("strnlen", &CStringChecker::evalstrnLength)
OpenPOWER on IntegriCloud