GP-2008: Fixing bad assumption that Mach-O segment commands precede load

commands with data in that segment
This commit is contained in:
Ryan Kurtz 2022-06-25 05:20:08 -04:00
parent d1313cff05
commit 547a729feb
2 changed files with 26 additions and 1 deletions

View File

@ -160,12 +160,30 @@ public class MachHeader implements StructConverter {
if (_parsed) {
return this;
}
// We must parse segment load commands first, so find and store their indexes separately
long currentIndex = _commandIndex;
List<Long> segmentIndexes = new ArrayList<>();
List<Long> nonSegmentIndexes = new ArrayList<>();
for (int i = 0; i < nCmds; ++i) {
_reader.setPointerIndex(currentIndex);
int type = _reader.readNextInt();
int size = _reader.readNextInt();
if (type == LoadCommandTypes.LC_SEGMENT || type == LoadCommandTypes.LC_SEGMENT_64) {
segmentIndexes.add(currentIndex);
}
else {
nonSegmentIndexes.add(currentIndex);
}
currentIndex += size;
}
List<Long> combinedIndexes = new ArrayList<>();
combinedIndexes.addAll(segmentIndexes); // Parse segments first
combinedIndexes.addAll(nonSegmentIndexes); // Parse everything else second
for (Long index : combinedIndexes) {
_reader.setPointerIndex(index);
LoadCommand lc = LoadCommandFactory.getLoadCommand(_reader, this, splitDyldCache);
_commands.add(lc);
currentIndex += lc.getCommandSize();
}
_parsed = true;
return this;

View File

@ -35,6 +35,10 @@ public class LoadCommandFactory {
/**
* Create and parses a {@link LoadCommand}
* <p>
* NOTE: Parsing {@link LoadCommand}s whose data lives in the __LINKEDIT segment require that
* the __LINKEDIT {@link SegmentCommand} have already been parsed. Thus, it is required that
* this method be called on {@link SegmentCommand}s before other types of {@link LoadCommand}s.
*
* @param reader A {@link BinaryReader reader} that points to the start of the load command
* @param header The {@link MachHeader header} associated with this load command
@ -156,6 +160,9 @@ public class LoadCommandFactory {
* Gets a {@link BinaryReader} that points to the given {@link MachHeader Mach-O header's}
* __LINKEDIT segment. Note that this segment may live in a different provider than
* the Mach-O header if a {@link SplitDyldCache} is being used.
* <p>
* NOTE: This method assumes that the __LINKEDIT segment {@link LoadCommand} has already been
* parsed.
*
* @param reader The {@link BinaryReader} used to read the given Mach-O header
* @param header The {@link MachHeader Mach-O header}