Skip to content

Commit 1fa073a

Browse files
authored
[MachO] Stop parsing past end of rebase/bind table (#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.
1 parent c5fdb5c commit 1fa073a

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
@@ -3501,15 +3501,17 @@ void MachORebaseEntry::moveNext() {
35013501
--RemainingLoopCount;
35023502
return;
35033503
}
3504-
// REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3505-
// pointer size. Therefore it is possible to reach the end without ever having
3506-
// seen REBASE_OPCODE_DONE.
3507-
if (Ptr == Opcodes.end()) {
3508-
Done = true;
3509-
return;
3510-
}
3504+
35113505
bool More = true;
35123506
while (More) {
3507+
// REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3508+
// pointer size. Therefore it is possible to reach the end without ever
3509+
// having seen REBASE_OPCODE_DONE.
3510+
if (Ptr == Opcodes.end()) {
3511+
Done = true;
3512+
return;
3513+
}
3514+
35133515
// Parse next opcode and set up next loop.
35143516
const uint8_t *OpcodeStart = Ptr;
35153517
uint8_t Byte = *Ptr++;
@@ -3838,15 +3840,17 @@ void MachOBindEntry::moveNext() {
38383840
--RemainingLoopCount;
38393841
return;
38403842
}
3841-
// BIND_OPCODE_DONE is only used for padding if we are not aligned to
3842-
// pointer size. Therefore it is possible to reach the end without ever having
3843-
// seen BIND_OPCODE_DONE.
3844-
if (Ptr == Opcodes.end()) {
3845-
Done = true;
3846-
return;
3847-
}
3843+
38483844
bool More = true;
38493845
while (More) {
3846+
// BIND_OPCODE_DONE is only used for padding if we are not aligned to
3847+
// pointer size. Therefore it is possible to reach the end without ever
3848+
// having seen BIND_OPCODE_DONE.
3849+
if (Ptr == Opcodes.end()) {
3850+
Done = true;
3851+
return;
3852+
}
3853+
38503854
// Parse next opcode and set up next loop.
38513855
const uint8_t *OpcodeStart = Ptr;
38523856
uint8_t Byte = *Ptr++;

0 commit comments

Comments
 (0)