]> granicus.if.org Git - clang/commitdiff
[analyzer] Make CStringChecker correctly calculate return value of mempcpy
authorAnna Zaks <ganna@apple.com>
Fri, 3 Oct 2014 21:48:54 +0000 (21:48 +0000)
committerAnna Zaks <ganna@apple.com>
Fri, 3 Oct 2014 21:48:54 +0000 (21:48 +0000)
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

lib/StaticAnalyzer/Checkers/CStringChecker.cpp
test/Analysis/bstring.c

index 0693bd6fd94df3ba24b3227730bf4a992f314095..e91a7e16802e7277662383291b58ca8ab2f2200a 100644 (file)
@@ -969,8 +969,13 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
       // Get the length to copy.
       if (Optional<NonLoc> lenValNonLoc = sizeVal.getAs<NonLoc>()) {
         // 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<loc::MemRegionVal>();
         SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add, 
-                                                          destRegVal,
+                                                          DestRegCharVal,
                                                           *lenValNonLoc, 
                                                           Dest->getType());
       
index 69d281afee4a14baedf41ae04f3566c34f046b92..824aa7c063b78dd52f065a8efed8a3ddaa74164b 100644 (file)
@@ -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}}