]> granicus.if.org Git - clang/commitdiff
[analyzer] Don't crash when copying an unknown number of bytes with memcpy(). Also...
authorJordy Rose <jediknil@belkadan.com>
Sat, 4 Jun 2011 01:47:27 +0000 (01:47 +0000)
committerJordy Rose <jediknil@belkadan.com>
Sat, 4 Jun 2011 01:47:27 +0000 (01:47 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132617 91177308-0d34-0410-b5e6-96231b3b80d8

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

index d9e49e4c4778df543ec20db08564ae4f6dc76fa7..2e3a1f1765961335159f7dea2850971c1b96917b 100644 (file)
@@ -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));
 }
 
index de88e9ae6fcf9c88382599b7bf01a0619f430dcc..68bbb1a5b2f5a117ea6b85e85d943fcac53f5649 100644 (file)
@@ -264,6 +264,12 @@ void mempcpy_unknown_size_warn (size_t n) {
     (void)*(char*)0; // no-warning
 }
 
+void mempcpy_unknownable_size (char *src, float n) {
+  char a[4];
+  // This used to crash because we don't model floats.
+  mempcpy(a, src, (size_t)n);
+}
+
 //===----------------------------------------------------------------------===
 // memmove()
 //===----------------------------------------------------------------------===