Merged in the release_32 branch of SAFECode on July 5, 2013.

llvm-svn: 185750
diff --git a/safecode/lib/CommonMemorySafety/InstrumentMemoryAccesses.cpp b/safecode/lib/CommonMemorySafety/InstrumentMemoryAccesses.cpp
index 1ec2e5f..efe6dba 100644
--- a/safecode/lib/CommonMemorySafety/InstrumentMemoryAccesses.cpp
+++ b/safecode/lib/CommonMemorySafety/InstrumentMemoryAccesses.cpp
@@ -30,6 +30,7 @@
 STATISTIC(LoadsInstrumented, "Loads instrumented");
 STATISTIC(StoresInstrumented, "Stores instrumented");
 STATISTIC(AtomicsInstrumented, "Atomic memory intrinsics instrumented");
+STATISTIC(IntrinsicsInstrumented, "Block memory intrinsics instrumented");
 
 namespace {
   class InstrumentMemoryAccesses : public FunctionPass,
@@ -66,6 +67,7 @@
     void visitStoreInst(StoreInst &SI);
     void visitAtomicCmpXchgInst(AtomicCmpXchgInst &I);
     void visitAtomicRMWInst(AtomicRMWInst &I);
+    void visitMemIntrinsic(MemIntrinsic &MI);
   };
 } // end anon namespace
 
@@ -149,3 +151,15 @@
   ++AtomicsInstrumented;
 }
 
+void InstrumentMemoryAccesses::visitMemIntrinsic(MemIntrinsic &MI) {
+  // Instrument llvm.mem[set|cpy|move].* calls with load/store checks.
+  Builder->SetInsertPoint(&MI);
+  Value *AccessSize = Builder->CreateIntCast(MI.getLength(), SizeTy,
+                                             /*isSigned=*/false);
+
+  // memcpy and memmove have a source memory area but memset doesn't
+  if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(&MI))
+    instrument(MTI->getSource(), AccessSize, LoadCheckFunction, MI);
+  instrument(MI.getDest(), AccessSize, StoreCheckFunction, MI);
+  ++IntrinsicsInstrumented;
+}
diff --git a/safecode/runtime/DebugRuntime/ExactCheck.cpp b/safecode/runtime/DebugRuntime/ExactCheck.cpp
index 426cb14..568a631 100755
--- a/safecode/runtime/DebugRuntime/ExactCheck.cpp
+++ b/safecode/runtime/DebugRuntime/ExactCheck.cpp
@@ -89,6 +89,13 @@
     }
   }
 
+  /*
+   * If the memory access accesses zero bytes, don't report an error.  This can
+   * happen with load/store checks on memcpy()/memset() calls.
+   */
+  if (!lslen)
+    return;
+
   failLSCheck (base, result, size, "unknown", 0);
   return;
 }
@@ -122,6 +129,13 @@
     }
   }
 
+  /*
+   * If the memory access accesses zero bytes, don't report an error.  This can
+   * happen with load/store checks on memcpy()/memset() calls.
+   */
+  if (!lslen)
+    return;
+
   failLSCheck (base, result, size, SourceFile, lineno);
   return;
 }
diff --git a/safecode/runtime/DebugRuntime/RuntimeChecks.cpp b/safecode/runtime/DebugRuntime/RuntimeChecks.cpp
index e236293..4a3638d 100755
--- a/safecode/runtime/DebugRuntime/RuntimeChecks.cpp
+++ b/safecode/runtime/DebugRuntime/RuntimeChecks.cpp
@@ -185,6 +185,14 @@
                  const char * SourceFilep,
                  unsigned lineno) {
   //
+  // If the memory access is zero bytes in length, don't report an error.
+  // This can happen on memcpy() and memset() calls that are instrumented
+  // with load/store checks.
+  //
+  if (length == 0)
+    return;
+
+  //
   // Check to see if the pointer points to an object within the pool.  If it
   // does, check to see if the last byte read/written will be within the same
   // object.  If so, then the check succeeds, so just return to the caller.
@@ -377,6 +385,14 @@
                    const char * SourceFilep,
                    unsigned lineno) {
   //
+  // If the memory access is zero bytes in length, don't report an error.
+  // This can happen on memcpy() and memset() calls that are instrumented
+  // with load/store checks.
+  //
+  if (length == 0)
+    return;
+
+  //
   // Check to see if the pointer points to an object within the pool.  If it
   // does, check to see if the last byte read/written will be within the same
   // object.  If so, then the check succeeds, so just return to the caller.
diff --git a/safecode/test/cstdlib/memcpy-004.c b/safecode/test/cstdlib/memcpy-004.c
new file mode 100644
index 0000000..a395247
--- /dev/null
+++ b/safecode/test/cstdlib/memcpy-004.c
@@ -0,0 +1,15 @@
+// RUN: test.sh -p -t %t %s
+#include <string.h>
+#include <assert.h>
+
+// Example of a memcpy() with zero length and bad input pointers
+
+int main()
+{
+  char src[] = "aaaaaaaaaab";
+  char dst[100];
+  volatile char * p;
+  p = memcpy(0, 0, 0);
+  printf ("%p\n", p);
+  return 0;
+}