From 6118a4aa50c887fd59fbc955aac1b53a3e3f4a46 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Fri, 3 Oct 2014 21:48:54 +0000 Subject: [PATCH] [analyzer] Make CStringChecker correctly calculate return value of mempcpy The return value of mempcpy is only correct when the destination type is one byte in size. This patch casts the argument to a char* so the calculation is also correct for structs, ints etc. A patch by Daniel Fahlgren! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@219024 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/CStringChecker.cpp | 7 +++- test/Analysis/bstring.c | 39 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 0693bd6fd9..e91a7e1680 100644 --- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -969,8 +969,13 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, // Get the length to copy. if (Optional lenValNonLoc = sizeVal.getAs()) { // Get the byte after the last byte copied. + SValBuilder &SvalBuilder = C.getSValBuilder(); + ASTContext &Ctx = SvalBuilder.getContext(); + QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy); + loc::MemRegionVal DestRegCharVal = SvalBuilder.evalCast(destRegVal, + CharPtrTy, Dest->getType()).castAs(); SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add, - destRegVal, + DestRegCharVal, *lenValNonLoc, Dest->getType()); diff --git a/test/Analysis/bstring.c b/test/Analysis/bstring.c index 69d281afee..824aa7c063 100644 --- a/test/Analysis/bstring.c +++ b/test/Analysis/bstring.c @@ -257,6 +257,45 @@ void mempcpy13() { mempcpy(a, 0, 0); // no-warning } +void mempcpy14() { + int src[] = {1, 2, 3, 4}; + int dst[5] = {0}; + int *p; + + p = mempcpy(dst, src, 4 * sizeof(int)); + + clang_analyzer_eval(p == &dst[4]); // expected-warning{{TRUE}} +} + +struct st { + int i; + int j; +}; + +void mempcpy15() { + struct st s1 = {0}; + struct st s2; + struct st *p1; + struct st *p2; + + p1 = (&s2) + 1; + p2 = mempcpy(&s2, &s1, sizeof(struct st)); + + clang_analyzer_eval(p1 == p2); // expected-warning{{TRUE}} +} + +void mempcpy16() { + struct st s1[10] = {{0}}; + struct st s2[10]; + struct st *p1; + struct st *p2; + + p1 = (&s2[0]) + 5; + p2 = mempcpy(&s2[0], &s1[0], 5 * sizeof(struct st)); + + clang_analyzer_eval(p1 == p2); // expected-warning{{TRUE}} +} + void mempcpy_unknown_size_warn (size_t n) { char a[4]; void *result = mempcpy(a, 0, n); // expected-warning{{Null pointer argument in call to memory copy function}} -- 2.40.0