Fix unaligned memory read issue exposed by ubsan
authorXinliang David Li <davidxl@google.com>
Tue, 17 Nov 2015 03:47:21 +0000 (03:47 +0000)
committerXinliang David Li <davidxl@google.com>
Tue, 17 Nov 2015 03:47:21 +0000 (03:47 +0000)
Indexed profile data as designed today does not guarantee
counter data to be well aligned, so reading needs to use
the slower form (with memcpy). This is less than ideal and
should be improved in the future (i.e., with fixed length
function key instead of variable length name key).

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

lib/ProfileData/InstrProf.cpp

index 762f00b48b6404dfd272508a9b868af045261fa5..ef7b19b2882099b899a097de2fa15c4cfb48a958 100644 (file)
@@ -184,11 +184,13 @@ void ValueProfRecord::serializeFrom(const InstrProfRecord &Record,
   }
 }
 
-template <class T> static T swapToHostOrder(T v, support::endianness Orig) {
-  if (Orig == getHostEndianness())
-    return v;
-  sys::swapByteOrder<T>(v);
-  return v;
+template <class T>
+static T swapToHostOrder(const unsigned char *&D, support::endianness Orig) {
+  using namespace support;
+  if (Orig == little)
+    return endian::readNext<T, little, unaligned>(D);
+  else
+    return endian::readNext<T, big, unaligned>(D);
 }
 
 // For writing/serializing,  Old is the host endianness, and  New is
@@ -278,10 +280,9 @@ ValueProfData::getValueProfData(const unsigned char *D,
   if (D + sizeof(ValueProfData) > BufferEnd)
     return instrprof_error::truncated;
 
-  uint32_t TotalSize = swapToHostOrder<uint32_t>(
-      reinterpret_cast<const uint32_t *>(D)[0], Endianness);
-  uint32_t NumValueKinds = swapToHostOrder<uint32_t>(
-      reinterpret_cast<const uint32_t *>(D)[1], Endianness);
+  const unsigned char *Header = D;
+  uint32_t TotalSize = swapToHostOrder<uint32_t>(Header, Endianness);
+  uint32_t NumValueKinds = swapToHostOrder<uint32_t>(Header, Endianness);
 
   if (D + TotalSize > BufferEnd)
     return instrprof_error::too_large;
@@ -307,7 +308,6 @@ ValueProfData::getValueProfData(const unsigned char *D,
       return instrprof_error::malformed;
   }
 
-  D += TotalSize;
   return std::move(VPD);
 }