diff options
author | Jordy Rose <jediknil@belkadan.com> | 2011-06-04 01:47:27 +0000 |
---|---|---|
committer | Jordy Rose <jediknil@belkadan.com> | 2011-06-04 01:47:27 +0000 |
commit | 3f8bb2fa289c956a66613b0f09e3df5e25d27c66 (patch) | |
tree | 6b160285a6ea3765017b4446310f665db2e6b3a2 /lib/StaticAnalyzer/Checkers/CStringChecker.cpp | |
parent | 7eb83caea14cbd3f0273004a6816c26040ac3755 (diff) |
[analyzer] Don't crash when copying an unknown number of bytes with memcpy(). Also handle all memcpy-family return values in evalCopyCommon(), rather than having some outside and some inside.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132617 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/CStringChecker.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index d9e49e4c47..2e3a1f1765 100644 --- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -748,19 +748,33 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, // bind the expr. if (IsMempcpy) { loc::MemRegionVal *destRegVal = dyn_cast<loc::MemRegionVal>(&destVal); + assert(destRegVal && "Destination should be a known MemRegionVal here"); // Get the length to copy. - SVal lenVal = state->getSVal(Size); - NonLoc *lenValNonLoc = dyn_cast<NonLoc>(&lenVal); + NonLoc *lenValNonLoc = dyn_cast<NonLoc>(&sizeVal); - // Get the byte after the last byte copied. - SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add, - *destRegVal, - *lenValNonLoc, - Dest->getType()); + if (lenValNonLoc) { + // Get the byte after the last byte copied. + SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add, + *destRegVal, + *lenValNonLoc, + Dest->getType()); - // The byte after the last byte copied is the return value. - state = state->BindExpr(CE, lastElement); + // The byte after the last byte copied is the return value. + state = state->BindExpr(CE, lastElement); + } else { + // If we don't know how much we copied, we can at least + // conjure a return value for later. + unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); + SVal result = + C.getSValBuilder().getConjuredSymbolVal(NULL, CE, Count); + state = state->BindExpr(CE, result); + } + + } else { + // All other copies return the destination buffer. + // (Well, bcopy() has a void return type, but this won't hurt.) + state = state->BindExpr(CE, destVal); } // Invalidate the destination. @@ -780,7 +794,7 @@ void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const { // The return value is the address of the destination buffer. const Expr *Dest = CE->getArg(0); const GRState *state = C.getState(); - state = state->BindExpr(CE, state->getSVal(Dest)); + evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true); } @@ -798,7 +812,7 @@ void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { // The return value is the address of the destination buffer. const Expr *Dest = CE->getArg(0); const GRState *state = C.getState(); - state = state->BindExpr(CE, state->getSVal(Dest)); + evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1)); } |