aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/MachOObjectFile.cpp
diff options
context:
space:
mode:
authorAdrian Prantl <aprantl@apple.com>2022-02-25 11:43:44 -0800
committerAdrian Prantl <aprantl@apple.com>2022-02-25 13:04:00 -0800
commitbbaeb1ee0ee03ffd5161f1414c8b36d7d7fcdbb7 (patch)
tree80358a57e6977910847701100f7c2c8c9736ffa6 /llvm/lib/Object/MachOObjectFile.cpp
parent2cd9a86da54f8be4eb2aff3e766b125cbdeb023f (diff)
downloadllvm-bbaeb1ee0ee03ffd5161f1414c8b36d7d7fcdbb7.zip
llvm-bbaeb1ee0ee03ffd5161f1414c8b36d7d7fcdbb7.tar.gz
llvm-bbaeb1ee0ee03ffd5161f1414c8b36d7d7fcdbb7.tar.bz2
Validate chained fixup image formats
This is part of a series of patches to upstream support for Mach-O chained fixups. Differential Revision: https://reviews.llvm.org/D113725
Diffstat (limited to 'llvm/lib/Object/MachOObjectFile.cpp')
-rw-r--r--llvm/lib/Object/MachOObjectFile.cpp54
1 files changed, 41 insertions, 13 deletions
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index 5d6e237..a3e0516 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -3259,13 +3259,13 @@ MachOChainedFixupEntry::MachOChainedFixupEntry(Error *E,
bool Parse)
: MachOAbstractFixupEntry(E, O) {
ErrorAsOutParameter e(E);
- if (Parse) {
- if (auto FixupTargetsOrErr = O->getDyldChainedFixupTargets())
- FixupTargets = *FixupTargetsOrErr;
- else {
- *E = FixupTargetsOrErr.takeError();
- return;
- }
+ if (!Parse)
+ return;
+ if (auto FixupTargetsOrErr = O->getDyldChainedFixupTargets())
+ FixupTargets = *FixupTargetsOrErr;
+ else {
+ *E = FixupTargetsOrErr.takeError();
+ return;
}
}
@@ -4763,11 +4763,11 @@ ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {
return makeArrayRef(Ptr, DyldInfo.lazy_bind_size);
}
-Expected<std::vector<ChainedFixupTarget>>
-MachOObjectFile::getDyldChainedFixupTargets() const {
+Expected<Optional<MachO::dyld_chained_fixups_header>>
+MachOObjectFile::getChainedFixupsHeader() const {
// Load the dyld chained fixups load command.
if (!DyldChainedFixupsLoadCmd)
- return std::vector<ChainedFixupTarget>();
+ return llvm::None;
auto DyldChainedFixupsOrErr = getStructOrErr<MachO::linkedit_data_command>(
*this, DyldChainedFixupsLoadCmd);
if (!DyldChainedFixupsOrErr)
@@ -4775,11 +4775,10 @@ MachOObjectFile::getDyldChainedFixupTargets() const {
MachO::linkedit_data_command DyldChainedFixups = DyldChainedFixupsOrErr.get();
// If the load command is present but the data offset has been zeroed out,
- // as is the case for dylib stubs, return an empty list of targets.
+ // as is the case for dylib stubs, return None (no error).
uint64_t CFHeaderOffset = DyldChainedFixups.dataoff;
- std::vector<ChainedFixupTarget> Targets;
if (CFHeaderOffset == 0)
- return Targets;
+ return DyldChainedFixupsOrErr.takeError();
// Load the dyld chained fixups header.
const char *CFHeaderPtr = getPtr(*this, CFHeaderOffset);
@@ -4798,6 +4797,35 @@ MachOObjectFile::getDyldChainedFixupTargets() const {
Twine("bad chained fixups: unknown imports format: ") +
Twine(CFHeader.imports_format));
+ // Validate the image format.
+ //
+ // Load the image starts.
+ uint64_t CFImageStartsOffset = (CFHeaderOffset + CFHeader.starts_offset);
+ if (CFHeader.starts_offset < sizeof(MachO::dyld_chained_fixups_header)) {
+ return malformedError(Twine("bad chained fixups: image starts offset ") +
+ Twine(CFHeader.starts_offset) +
+ " overlaps with chained fixups header");
+ }
+ uint32_t EndOffset = DyldChainedFixups.dataoff + DyldChainedFixups.datasize;
+ if (CFImageStartsOffset + sizeof(MachO::dyld_chained_starts_in_image) >
+ EndOffset) {
+ return malformedError(Twine("bad chained fixups: image starts end ") +
+ Twine(CFImageStartsOffset +
+ sizeof(MachO::dyld_chained_starts_in_image)) +
+ " extends past end " + Twine(EndOffset));
+ }
+
+ return CFHeader;
+}
+
+Expected<std::vector<ChainedFixupTarget>>
+MachOObjectFile::getDyldChainedFixupTargets() const {
+ auto CFHeaderOrErr = getChainedFixupsHeader();
+ if (!CFHeaderOrErr)
+ return CFHeaderOrErr.takeError();
+ std::vector<ChainedFixupTarget> Targets;
+ if (!(*CFHeaderOrErr))
+ return Targets;
return Targets;
}