Index: llvm/include/llvm/ProfileData/InstrProfReader.h =================================================================== --- llvm/include/llvm/ProfileData/InstrProfReader.h +++ llvm/include/llvm/ProfileData/InstrProfReader.h @@ -268,8 +268,11 @@ return (const char *)ValueDataStart; } - const uint64_t *getCounter(IntPtrT CounterPtr) const { - ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t); + ptrdiff_t getCounterOffset(IntPtrT CounterPtr) const { + return (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t); + } + + const uint64_t *getCounter(ptrdiff_t Offset) const { return CountersStart + Offset; } Index: llvm/lib/ProfileData/InstrProfReader.cpp =================================================================== --- llvm/lib/ProfileData/InstrProfReader.cpp +++ llvm/lib/ProfileData/InstrProfReader.cpp @@ -413,14 +413,17 @@ if (NumCounters == 0) return error(instrprof_error::malformed); - auto RawCounts = makeArrayRef(getCounter(CounterPtr), NumCounters); auto *NamesStartAsCounter = reinterpret_cast(NamesStart); - // Check bounds. - if (RawCounts.data() < CountersStart || - RawCounts.data() + RawCounts.size() > NamesStartAsCounter) + // Check bounds. Note that the counter pointer embedded in the data record + // may itself be corrupt. + ptrdiff_t CounterOffset = getCounterOffset(CounterPtr); + if (CounterOffset < 0 || + CounterOffset >= (NamesStartAsCounter - CountersStart)) return error(instrprof_error::malformed); + auto RawCounts = makeArrayRef(getCounter(CounterOffset), NumCounters); + if (ShouldSwapBytes) { Record.Counts.clear(); Record.Counts.reserve(RawCounts.size()); Index: llvm/test/tools/llvm-profdata/malformed-ptr-to-counter-array.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-profdata/malformed-ptr-to-counter-array.test @@ -0,0 +1,5 @@ +REQUIRES: zlib + +RUN: not llvm-profdata merge -o /dev/null %p/Inputs/malformed-ptr-to-counter-array.profraw 2>&1 | FileCheck %s + +CHECK: Malformed instrumentation profile data