[UB] Fix a nasty place where we would pass null pointers to memcpy.
authorChandler Carruth <chandlerc@gmail.com>
Tue, 4 Aug 2015 00:44:07 +0000 (00:44 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Tue, 4 Aug 2015 00:44:07 +0000 (00:44 +0000)
This happens to work, but is not guaranteed to work. Indeed, most memcpy
interfaces in Linux-land annotate these arguments as nonnull, and GCC
and LLVM both can and do optimized based upon that. When they do so,
they might legitimately have miscompiled code calling this routine with
two valid iterators, 'nullptr' and 'nullptr'. There was even code doing
precisely this because StringRef().begin() and StringRef().end() both
produce null pointers.

This was found by UBSan.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243927 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/SmallVector.h

index 5b208b76a21fa8c465b2b7645c16b649c8e4000e..b9384702c3ba0588d3a402e677a9805d4c471729 100644 (file)
@@ -315,8 +315,10 @@ protected:
                                            T2>::value>::type * = nullptr) {
     // Use memcpy for PODs iterated by pointers (which includes SmallVector
     // iterators): std::uninitialized_copy optimizes to memmove, but we can
-    // use memcpy here.
-    memcpy(Dest, I, (E-I)*sizeof(T));
+    // use memcpy here. Note that I and E are iterators and thus might be
+    // invalid for memcpy if they are equal.
+    if (I != E)
+      memcpy(Dest, I, (E - I) * sizeof(T));
   }
 
   /// Double the size of the allocated memory, guaranteeing space for at