Skip to content
This repository has been archived by the owner on Mar 28, 2020. It is now read-only.
/ swift-llvm Public archive

Commit

Permalink
[InstrProf] Tighten a check for malformed data records in raw profiles
Browse files Browse the repository at this point in the history
The check needs to validate a counter offset before performing pointer
arithmetic with the (potentially corrupt) offset.

Found by UBSan's pointer overflow check.

rdar://54843625

Differential Revision: https://reviews.llvm.org/D66979

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@370826 91177308-0d34-0410-b5e6-96231b3b80d8
(cherry picked from commit 1ae7a2b)
  • Loading branch information
vedantk committed Oct 9, 2019
1 parent 4dd8558 commit c4f6a89
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 6 deletions.
10 changes: 8 additions & 2 deletions include/llvm/ProfileData/InstrProfReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,14 @@ class RawInstrProfReader : public InstrProfReader {
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;
}

Expand Down
14 changes: 10 additions & 4 deletions lib/ProfileData/InstrProfReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,13 +413,19 @@ Error RawInstrProfReader<IntPtrT>::readRawCounts(
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();
Expand Down
Binary file not shown.
5 changes: 5 additions & 0 deletions test/tools/llvm-profdata/malformed-ptr-to-counter-array.test
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit c4f6a89

Please sign in to comment.