diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c --- a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c @@ -95,10 +95,13 @@ * have a fixed length. */ static int WriteOneBinaryId(ProfDataWriter *Writer, uint64_t BinaryIdLen, - const uint8_t *BinaryIdData) { + const uint8_t *BinaryIdData, + uint64_t BinaryIdPadding) { ProfDataIOVec BinaryIdIOVec[] = { {&BinaryIdLen, sizeof(uint64_t), 1, 0}, - {BinaryIdData, sizeof(uint8_t), BinaryIdLen, 0}}; + {BinaryIdData, sizeof(uint8_t), BinaryIdLen, 0}, + {NULL, sizeof(uint8_t), BinaryIdPadding, 1}, + }; if (Writer->Write(Writer, BinaryIdIOVec, sizeof(BinaryIdIOVec) / sizeof(*BinaryIdIOVec))) return -1; @@ -130,11 +133,12 @@ uint64_t BinaryIdLen = Note->n_descsz; const uint8_t *BinaryIdData = (const uint8_t *)(NoteName + RoundUp(Note->n_namesz, 4)); - if (Writer != NULL && - WriteOneBinaryId(Writer, BinaryIdLen, BinaryIdData) == -1) + uint8_t BinaryIdPadding = __llvm_profile_get_num_padding_bytes(BinaryIdLen); + if (Writer != NULL && WriteOneBinaryId(Writer, BinaryIdLen, BinaryIdData, + BinaryIdPadding) == -1) return -1; - BinaryIdSize = sizeof(BinaryIdLen) + BinaryIdLen; + BinaryIdSize = sizeof(BinaryIdLen) + BinaryIdLen + BinaryIdPadding; } return BinaryIdSize; diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp --- a/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/llvm/lib/ProfileData/InstrProfReader.cpp @@ -367,6 +367,9 @@ return error(instrprof_error::unsupported_version); BinaryIdsSize = swap(Header.BinaryIdsSize); + if (BinaryIdsSize % sizeof(uint64_t)) + return error(instrprof_error::malformed); + CountersDelta = swap(Header.CountersDelta); NamesDelta = swap(Header.NamesDelta); auto DataSize = swap(Header.DataSize); @@ -520,6 +523,10 @@ return success(); } +static size_t RoundUp(size_t size, size_t align) { + return (size + align - 1) & ~(align - 1); +} + template Error RawInstrProfReader::printBinaryIds(raw_ostream &OS) { if (BinaryIdsSize == 0) @@ -527,8 +534,21 @@ OS << "Binary IDs: \n"; const uint8_t *BI = BinaryIdsStart; - while (BI < BinaryIdsStart + BinaryIdsSize) { + const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize; + while (BI < BIEnd) { + size_t Remaining = BIEnd - BI; + + // There should be enough left to read the binary ID size field. + if (Remaining < sizeof(uint64_t)) + return make_error(instrprof_error::malformed); + uint64_t BinaryIdLen = swap(*reinterpret_cast(BI)); + + // There should be enough left to read the binary ID size field, and the + // binary ID. + if (Remaining < sizeof(BinaryIdLen) + BinaryIdLen) + return make_error(instrprof_error::malformed); + // Increment by binary id length data type size. BI += sizeof(BinaryIdLen); if (BI > (const uint8_t *)DataBuffer->getBufferEnd()) @@ -538,8 +558,9 @@ OS << format("%02x", BI[I]); OS << "\n"; - // Increment by binary id data length. - BI += BinaryIdLen; + // Increment by binary id data length, rounded to the next 8 bytes. This + // accounts for the zero-padding after each build ID. + BI += RoundUp(BinaryIdLen, sizeof(uint64_t)); if (BI > (const uint8_t *)DataBuffer->getBufferEnd()) return make_error(instrprof_error::malformed); }