Skip to content

Commit 2581ed7

Browse files
committed
[MachO] Stop parsing past end of rebase/bind table (llvm#93897)
`MachORebaseEntry::moveNext()` and `MachOBindEntry::moveNext()` assume that the rebase/bind table ends with `{REBASE|BIND}_OPCODE_DONE` or an actual rebase/bind. However a valid rebase/bind table might also end with other effectively no-op opcodes, which caused the parser to move past the end and go into the next table, resulting in corrupted entries or infinite loops. (cherry picked from commit 1fa073a)
1 parent 0872cb5 commit 2581ed7

File tree

3 files changed

+429
-14
lines changed

3 files changed

+429
-14
lines changed

llvm/lib/Object/MachOObjectFile.cpp

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3497,15 +3497,17 @@ void MachORebaseEntry::moveNext() {
34973497
--RemainingLoopCount;
34983498
return;
34993499
}
3500-
// REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3501-
// pointer size. Therefore it is possible to reach the end without ever having
3502-
// seen REBASE_OPCODE_DONE.
3503-
if (Ptr == Opcodes.end()) {
3504-
Done = true;
3505-
return;
3506-
}
3500+
35073501
bool More = true;
35083502
while (More) {
3503+
// REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3504+
// pointer size. Therefore it is possible to reach the end without ever
3505+
// having seen REBASE_OPCODE_DONE.
3506+
if (Ptr == Opcodes.end()) {
3507+
Done = true;
3508+
return;
3509+
}
3510+
35093511
// Parse next opcode and set up next loop.
35103512
const uint8_t *OpcodeStart = Ptr;
35113513
uint8_t Byte = *Ptr++;
@@ -3834,15 +3836,17 @@ void MachOBindEntry::moveNext() {
38343836
--RemainingLoopCount;
38353837
return;
38363838
}
3837-
// BIND_OPCODE_DONE is only used for padding if we are not aligned to
3838-
// pointer size. Therefore it is possible to reach the end without ever having
3839-
// seen BIND_OPCODE_DONE.
3840-
if (Ptr == Opcodes.end()) {
3841-
Done = true;
3842-
return;
3843-
}
3839+
38443840
bool More = true;
38453841
while (More) {
3842+
// BIND_OPCODE_DONE is only used for padding if we are not aligned to
3843+
// pointer size. Therefore it is possible to reach the end without ever
3844+
// having seen BIND_OPCODE_DONE.
3845+
if (Ptr == Opcodes.end()) {
3846+
Done = true;
3847+
return;
3848+
}
3849+
38463850
// Parse next opcode and set up next loop.
38473851
const uint8_t *OpcodeStart = Ptr;
38483852
uint8_t Byte = *Ptr++;

0 commit comments

Comments
 (0)