Skip to content

Commit

Permalink
[llvm][MachO] Fix integer truncation in rebase/bind parsing (llvm#89337)
Browse files Browse the repository at this point in the history
`Count` and `Skip` should use `uint64_t` as they are encoded/decoded
using 64-bit ULEB128.

In `*_OPCODE_DO_*_ULEB_TIMES_SKIPPING_ULEB`, `Skip` could be encoded as
a two's complement for moving `SegmentOffset` backwards. Having a 32-bit
`Skip` truncates the encoded value and leads to a malformed
`AdvanceAmount`
and invalid `SegmentOffset` that extends past valid sections.
  • Loading branch information
zixu-w authored May 9, 2024
1 parent ea126ae commit b910beb
Show file tree
Hide file tree
Showing 4 changed files with 534 additions and 17 deletions.
15 changes: 8 additions & 7 deletions llvm/include/llvm/Object/MachO.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ class BindRebaseSegInfo {
BindRebaseSegInfo(const MachOObjectFile *Obj);

// Used to check a Mach-O Bind or Rebase entry for errors when iterating.
const char* checkSegAndOffsets(int32_t SegIndex, uint64_t SegOffset,
uint8_t PointerSize, uint32_t Count=1,
uint32_t Skip=0);
const char *checkSegAndOffsets(int32_t SegIndex, uint64_t SegOffset,
uint8_t PointerSize, uint64_t Count = 1,
uint64_t Skip = 0);
// Used with valid SegIndex/SegOffset values from checked entries.
StringRef segmentName(int32_t SegIndex);
StringRef sectionName(int32_t SegIndex, uint64_t SegOffset);
Expand Down Expand Up @@ -576,8 +576,9 @@ class MachOObjectFile : public ObjectFile {
//
// This is used by MachOBindEntry::moveNext() to validate a MachOBindEntry.
const char *BindEntryCheckSegAndOffsets(int32_t SegIndex, uint64_t SegOffset,
uint8_t PointerSize, uint32_t Count=1,
uint32_t Skip=0) const {
uint8_t PointerSize,
uint64_t Count = 1,
uint64_t Skip = 0) const {
return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset,
PointerSize, Count, Skip);
}
Expand All @@ -591,8 +592,8 @@ class MachOObjectFile : public ObjectFile {
const char *RebaseEntryCheckSegAndOffsets(int32_t SegIndex,
uint64_t SegOffset,
uint8_t PointerSize,
uint32_t Count=1,
uint32_t Skip=0) const {
uint64_t Count = 1,
uint64_t Skip = 0) const {
return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset,
PointerSize, Count, Skip);
}
Expand Down
20 changes: 10 additions & 10 deletions llvm/lib/Object/MachOObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3515,7 +3515,7 @@ void MachORebaseEntry::moveNext() {
uint8_t Byte = *Ptr++;
uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
uint32_t Count, Skip;
uint64_t Count, Skip;
const char *error = nullptr;
switch (Opcode) {
case MachO::REBASE_OPCODE_DONE:
Expand Down Expand Up @@ -3854,7 +3854,7 @@ void MachOBindEntry::moveNext() {
uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
int8_t SignExtended;
const uint8_t *SymStart;
uint32_t Count, Skip;
uint64_t Count, Skip;
const char *error = nullptr;
switch (Opcode) {
case MachO::BIND_OPCODE_DONE:
Expand Down Expand Up @@ -4384,18 +4384,18 @@ BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
// that fully contains a pointer at that location. Multiple fixups in a bind
// (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
// be tested via the Count and Skip parameters.
const char * BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex,
uint64_t SegOffset,
uint8_t PointerSize,
uint32_t Count,
uint32_t Skip) {
const char *BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex,
uint64_t SegOffset,
uint8_t PointerSize,
uint64_t Count,
uint64_t Skip) {
if (SegIndex == -1)
return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
if (SegIndex >= MaxSegIndex)
return "bad segIndex (too large)";
for (uint32_t i = 0; i < Count; ++i) {
uint32_t Start = SegOffset + i * (PointerSize + Skip);
uint32_t End = Start + PointerSize;
for (uint64_t i = 0; i < Count; ++i) {
uint64_t Start = SegOffset + i * (PointerSize + Skip);
uint64_t End = Start + PointerSize;
bool Found = false;
for (const SectionInfo &SI : Sections) {
if (SI.SegmentIndex != SegIndex)
Expand Down
Loading

0 comments on commit b910beb

Please sign in to comment.