From 630423e3797639336875edce07b4210dd2cf33a1 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Tue, 4 Aug 2015 00:44:07 +0000 Subject: [PATCH] [UB] Fix a nasty place where we would pass null pointers to memcpy. 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. llvm-svn: 243927 --- llvm/include/llvm/ADT/SmallVector.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h index 5b208b7..b938470 100644 --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/llvm/include/llvm/ADT/SmallVector.h @@ -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 -- 2.7.4