[Object, MachO] Don't crash on invalid MachO load commands.
Summary:
Currently all load commands are parsed in MachOObjectFile constructor.
If the next load command cannot be parsed, or if command size is too
small, properly report it through the error code and fail to construct
the object, instead of crashing the program.
Test Plan: regression test suite
Reviewers: rafael, filcab
Subscribers: llvm-commits
llvm-svn: 239080
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index c1d1383..3262c6c 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -194,24 +194,27 @@
return Sect.flags;
}
-static MachOObjectFile::LoadCommandInfo
+static ErrorOr<MachOObjectFile::LoadCommandInfo>
getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) {
+ auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr);
+ if (!CmdOrErr)
+ return CmdOrErr.getError();
+ if (CmdOrErr->cmdsize < 8)
+ return object_error::macho_small_load_command;
MachOObjectFile::LoadCommandInfo Load;
Load.Ptr = Ptr;
- Load.C = getStruct<MachO::load_command>(Obj, Load.Ptr);
- if (Load.C.cmdsize < 8)
- report_fatal_error("Load command with size < 8 bytes.");
+ Load.C = CmdOrErr.get();
return Load;
}
-static MachOObjectFile::LoadCommandInfo
+static ErrorOr<MachOObjectFile::LoadCommandInfo>
getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
: sizeof(MachO::mach_header);
return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize));
}
-static MachOObjectFile::LoadCommandInfo
+static ErrorOr<MachOObjectFile::LoadCommandInfo>
getNextLoadCommandInfo(const MachOObjectFile *Obj,
const MachOObjectFile::LoadCommandInfo &L) {
return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize);
@@ -251,7 +254,12 @@
MachO::LoadCommandType SegmentLoadType = is64Bit() ?
MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;
- LoadCommandInfo Load = getFirstLoadCommandInfo(this);
+ auto LoadOrErr = getFirstLoadCommandInfo(this);
+ if (!LoadOrErr) {
+ EC = LoadOrErr.getError();
+ return;
+ }
+ LoadCommandInfo Load = LoadOrErr.get();
for (unsigned I = 0; I < LoadCommandCount; ++I) {
LoadCommands.push_back(Load);
if (Load.C.cmd == MachO::LC_SYMTAB) {
@@ -318,8 +326,14 @@
Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
Libraries.push_back(Load.Ptr);
}
- if (I < LoadCommandCount - 1)
- Load = getNextLoadCommandInfo(this, Load);
+ if (I < LoadCommandCount - 1) {
+ auto LoadOrErr = getNextLoadCommandInfo(this, Load);
+ if (!LoadOrErr) {
+ EC = LoadOrErr.getError();
+ return;
+ }
+ Load = LoadOrErr.get();
+ }
}
assert(LoadCommands.size() == LoadCommandCount);
}