Fix unaligned memory read issue exposed by ubsan

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).

llvm-svn: 253309
This commit is contained in:
Xinliang David Li 2015-11-17 03:47:21 +00:00
parent 055a08a488
commit b8c3ad1d05
1 changed files with 10 additions and 10 deletions

View 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);
}