[llvm] r239080 - [Object, MachO] Don't crash on invalid MachO load commands.
Alexey Samsonov
vonosmas at gmail.com
Thu Jun 4 12:57:46 PDT 2015
Author: samsonov
Date: Thu Jun 4 14:57:46 2015
New Revision: 239080
URL: http://llvm.org/viewvc/llvm-project?rev=239080&view=rev
Log:
[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
Modified:
llvm/trunk/include/llvm/Object/Error.h
llvm/trunk/lib/Object/Error.cpp
llvm/trunk/lib/Object/MachOObjectFile.cpp
llvm/trunk/test/Object/macho-invalid.test
Modified: llvm/trunk/include/llvm/Object/Error.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Error.h?rev=239080&r1=239079&r2=239080&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/Error.h (original)
+++ llvm/trunk/include/llvm/Object/Error.h Thu Jun 4 14:57:46 2015
@@ -28,6 +28,7 @@ enum class object_error {
parse_failed,
unexpected_eof,
bitcode_section_not_found,
+ macho_small_load_command,
};
inline std::error_code make_error_code(object_error e) {
Modified: llvm/trunk/lib/Object/Error.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/Error.cpp?rev=239080&r1=239079&r2=239080&view=diff
==============================================================================
--- llvm/trunk/lib/Object/Error.cpp (original)
+++ llvm/trunk/lib/Object/Error.cpp Thu Jun 4 14:57:46 2015
@@ -44,6 +44,8 @@ std::string _object_error_category::mess
return "The end of the file was unexpectedly encountered";
case object_error::bitcode_section_not_found:
return "Bitcode section not found in object file";
+ case object_error::macho_small_load_command:
+ return "Mach-O load command with size < 8 bytes";
}
llvm_unreachable("An enumerator of object_error does not have a message "
"defined.");
Modified: llvm/trunk/lib/Object/MachOObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/MachOObjectFile.cpp?rev=239080&r1=239079&r2=239080&view=diff
==============================================================================
--- llvm/trunk/lib/Object/MachOObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/MachOObjectFile.cpp Thu Jun 4 14:57:46 2015
@@ -194,24 +194,27 @@ static uint32_t getSectionFlags(const Ma
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 @@ MachOObjectFile::MachOObjectFile(MemoryB
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 @@ MachOObjectFile::MachOObjectFile(MemoryB
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);
}
Modified: llvm/trunk/test/Object/macho-invalid.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/macho-invalid.test?rev=239080&r1=239079&r2=239080&view=diff
==============================================================================
--- llvm/trunk/test/Object/macho-invalid.test (original)
+++ llvm/trunk/test/Object/macho-invalid.test Thu Jun 4 14:57:46 2015
@@ -3,13 +3,13 @@ RUN: llvm-objdump -private-headers %p/In
RUN: not llvm-objdump -private-headers %p/Inputs/macho64-invalid-incomplete-load-command 2>&1 \
RUN: | FileCheck -check-prefix INCOMPLETE-LOADC %s
-INCOMPLETE-LOADC: Malformed MachO file
+INCOMPLETE-LOADC: Invalid data was encountered while parsing the file.
RUN: not llvm-objdump -private-headers %p/Inputs/macho-invalid-too-small-load-command 2>&1 \
RUN: | FileCheck -check-prefix SMALL-LOADC-SIZE %s
RUN: not llvm-objdump -private-headers %p/Inputs/macho64-invalid-too-small-load-command 2>&1 \
RUN: | FileCheck -check-prefix SMALL-LOADC-SIZE %s
-SMALL-LOADC-SIZE: Load command with size < 8 bytes
+SMALL-LOADC-SIZE: Mach-O load command with size < 8 bytes
RUN: not llvm-objdump -private-headers %p/Inputs/macho-invalid-too-small-segment-load-command 2>&1 \
RUN: | FileCheck -check-prefix SMALL-SEGLOADC-SIZE %s
More information about the llvm-commits
mailing list