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 | 097c5397a8a04000cb4785a5bc04d419e04c5080 (patch) | |
tree | 88068769c668a95b42b2dcf54394db7a346b4e52 /clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp | |
parent | c73aa1ee813b3e3b4cd21d3cc6d570ffd0607721 (diff) | |
download | bcm5719-llvm-097c5397a8a04000cb4785a5bc04d419e04c5080.tar.gz bcm5719-llvm-097c5397a8a04000cb4785a5bc04d419e04c5080.zip |
[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.
llvm-svn: 132617
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index d9e49e4c477..2e3a1f17659 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/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)); } |