diff options
author | Zixu Wang <9819235+zixu-w@users.noreply.github.com> | 2024-05-08 18:53:15 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-08 18:53:15 -0700 |
commit | b910bebc300dafb30569cecc3017b446ea8eafa0 (patch) | |
tree | 161baf5e8348f866053eabe037ef4322a920546e /llvm/lib/Object/MachOObjectFile.cpp | |
parent | ea126aebdc9d8205016f355d85dbf1c15f2f4b28 (diff) | |
download | llvm-b910bebc300dafb30569cecc3017b446ea8eafa0.zip llvm-b910bebc300dafb30569cecc3017b446ea8eafa0.tar.gz llvm-b910bebc300dafb30569cecc3017b446ea8eafa0.tar.bz2 |
[llvm][MachO] Fix integer truncation in rebase/bind parsing (#89337)
`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.
Diffstat (limited to 'llvm/lib/Object/MachOObjectFile.cpp')
-rw-r--r-- | llvm/lib/Object/MachOObjectFile.cpp | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp index 06186ad..ef390ce 100644 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -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: @@ -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: @@ -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) |