return (const char *)ValueDataStart;
}
- const uint64_t *getCounter(IntPtrT CounterPtr) const {
- ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
+ /// Get the offset of \p CounterPtr from the start of the counters section of
+ /// the profile. The offset has units of "number of counters", i.e. increasing
+ /// the offset by 1 corresponds to an increase in the *byte offset* by 8.
+ ptrdiff_t getCounterOffset(IntPtrT CounterPtr) const {
+ return (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t);
+ }
+
+ const uint64_t *getCounter(ptrdiff_t Offset) const {
return CountersStart + Offset;
}
if (NumCounters == 0)
return error(instrprof_error::malformed);
- auto RawCounts = makeArrayRef(getCounter(CounterPtr), NumCounters);
auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart);
+ ptrdiff_t MaxNumCounters = NamesStartAsCounter - CountersStart;
- // 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.
+ if (NumCounters > MaxNumCounters)
return error(instrprof_error::malformed);
+ ptrdiff_t CounterOffset = getCounterOffset(CounterPtr);
+ if (CounterOffset < 0 || CounterOffset > MaxNumCounters ||
+ (CounterOffset + NumCounters) > MaxNumCounters)
+ return error(instrprof_error::malformed);
+
+ auto RawCounts = makeArrayRef(getCounter(CounterOffset), NumCounters);
if (ShouldSwapBytes) {
Record.Counts.clear();