diff options
15 files changed, 120 insertions, 7 deletions
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp index 2435340b66e..b57955b35da 100644 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -504,6 +504,81 @@ static Error checkLinkeditDataCommand(const MachOObjectFile *Obj, return Error::success(); } +static Error checkDyldInfoCommand(const MachOObjectFile *Obj, + const MachOObjectFile::LoadCommandInfo &Load, + uint32_t LoadCommandIndex, + const char **LoadCmd, const char *CmdName) { + if (Load.C.cmdsize < sizeof(MachO::dyld_info_command)) + return malformedError("load command " + Twine(LoadCommandIndex) + " " + + CmdName + " cmdsize too small"); + if (*LoadCmd != nullptr) + return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY " + "command"); + MachO::dyld_info_command DyldInfo = + getStruct<MachO::dyld_info_command>(Obj, Load.Ptr); + if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command)) + return malformedError(Twine(CmdName) + " command " + + Twine(LoadCommandIndex) + " has incorrect cmdsize"); + uint64_t FileSize = Obj->getData().size(); + if (DyldInfo.rebase_off > FileSize) + return malformedError("rebase_off field of " + Twine(CmdName) + + " command " + Twine(LoadCommandIndex) + " extends " + "past the end of the file"); + uint64_t BigSize = DyldInfo.rebase_off; + BigSize += DyldInfo.rebase_size; + if (BigSize > FileSize) + return malformedError("rebase_off field plus rebase_size field of " + + Twine(CmdName) + " command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + if (DyldInfo.bind_off > FileSize) + return malformedError("bind_off field of " + Twine(CmdName) + + " command " + Twine(LoadCommandIndex) + " extends " + "past the end of the file"); + BigSize = DyldInfo.bind_off; + BigSize += DyldInfo.bind_size; + if (BigSize > FileSize) + return malformedError("bind_off field plus bind_size field of " + + Twine(CmdName) + " command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + if (DyldInfo.weak_bind_off > FileSize) + return malformedError("weak_bind_off field of " + Twine(CmdName) + + " command " + Twine(LoadCommandIndex) + " extends " + "past the end of the file"); + BigSize = DyldInfo.weak_bind_off; + BigSize += DyldInfo.weak_bind_size; + if (BigSize > FileSize) + return malformedError("weak_bind_off field plus weak_bind_size field of " + + Twine(CmdName) + " command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + if (DyldInfo.lazy_bind_off > FileSize) + return malformedError("lazy_bind_off field of " + Twine(CmdName) + + " command " + Twine(LoadCommandIndex) + " extends " + "past the end of the file"); + BigSize = DyldInfo.lazy_bind_off; + BigSize += DyldInfo.lazy_bind_size; + if (BigSize > FileSize) + return malformedError("lazy_bind_off field plus lazy_bind_size field of " + + Twine(CmdName) + " command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + if (DyldInfo.export_off > FileSize) + return malformedError("export_off field of " + Twine(CmdName) + + " command " + Twine(LoadCommandIndex) + " extends " + "past the end of the file"); + BigSize = DyldInfo.export_off; + BigSize += DyldInfo.export_size; + if (BigSize > FileSize) + return malformedError("export_off field plus export_size field of " + + Twine(CmdName) + " command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + *LoadCmd = Load.Ptr; + return Error::success(); +} + Expected<std::unique_ptr<MachOObjectFile>> MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits) { @@ -587,14 +662,14 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, if ((Err = checkLinkeditDataCommand(this, Load, I, &LinkOptHintsLoadCmd, "LC_LINKER_OPTIMIZATION_HINT"))) return; - } else if (Load.C.cmd == MachO::LC_DYLD_INFO || - Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { - // Multiple dyldinfo load commands - if (DyldInfoLoadCmd) { - Err = malformedError("Multiple dyldinfo load commands"); + } else if (Load.C.cmd == MachO::LC_DYLD_INFO) { + if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, + "LC_DYLD_INFO"))) + return; + } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { + if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, + "LC_DYLD_INFO_ONLY"))) return; - } - DyldInfoLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_UUID) { // Multiple UUID load commands if (UuidLoadCmd) { diff --git a/llvm/test/Object/Inputs/macho-invalid-dyldinfo-bind_off-bind_size b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-bind_off-bind_size Binary files differnew file mode 100644 index 00000000000..b332f1dbf84 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-bind_off-bind_size diff --git a/llvm/test/Object/Inputs/macho-invalid-dyldinfo-export_off-export_size b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-export_off-export_size Binary files differnew file mode 100644 index 00000000000..212c97ef3ad --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-export_off-export_size diff --git a/llvm/test/Object/Inputs/macho-invalid-dyldinfo-lazy_bind_off-lazy_bind_size b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-lazy_bind_off-lazy_bind_size Binary files differnew file mode 100644 index 00000000000..86685a50e74 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-lazy_bind_off-lazy_bind_size diff --git a/llvm/test/Object/Inputs/macho-invalid-dyldinfo-more-than-one b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-more-than-one Binary files differnew file mode 100644 index 00000000000..451c4aba326 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-more-than-one diff --git a/llvm/test/Object/Inputs/macho-invalid-dyldinfo-rebase_off b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-rebase_off Binary files differnew file mode 100644 index 00000000000..0b56623bc62 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-rebase_off diff --git a/llvm/test/Object/Inputs/macho-invalid-dyldinfo-rebase_off-rebase_size b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-rebase_off-rebase_size Binary files differnew file mode 100644 index 00000000000..c28a3bc91b2 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-rebase_off-rebase_size diff --git a/llvm/test/Object/Inputs/macho-invalid-dyldinfo-small b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-small Binary files differnew file mode 100644 index 00000000000..7ccb261eb9f --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-small diff --git a/llvm/test/Object/Inputs/macho-invalid-dyldinfo-weak_bind_off-weak_bind_size b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-weak_bind_off-weak_bind_size Binary files differnew file mode 100644 index 00000000000..a332326c4e2 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dyldinfo-weak_bind_off-weak_bind_size diff --git a/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-bad-size b/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-bad-size Binary files differnew file mode 100644 index 00000000000..084e12eed3d --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-bad-size diff --git a/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-bind_off b/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-bind_off Binary files differnew file mode 100644 index 00000000000..3bad96820f5 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-bind_off diff --git a/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-export_off b/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-export_off Binary files differnew file mode 100644 index 00000000000..3277775a84b --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-export_off diff --git a/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-lazy_bind_off b/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-lazy_bind_off Binary files differnew file mode 100644 index 00000000000..375f6a32339 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-lazy_bind_off diff --git a/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-weak_bind_off b/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-weak_bind_off Binary files differnew file mode 100644 index 00000000000..52c9053310f --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dyldinfoonly-weak_bind_off diff --git a/llvm/test/Object/macho-invalid.test b/llvm/test/Object/macho-invalid.test index 91a325ad7d1..8868b88cff4 100644 --- a/llvm/test/Object/macho-invalid.test +++ b/llvm/test/Object/macho-invalid.test @@ -224,3 +224,41 @@ INVALID-LINKOPTHINT-DATAOFF: macho-invalid-linkopthint-dataoff': truncated or ma RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dataincode-dataoff-datasize 2>&1 | FileCheck -check-prefix INVALID-DATAINCODE-DATAOFF-DATASIZE %s INVALID-DATAINCODE-DATAOFF-DATASIZE: macho-invalid-dataincode-dataoff-datasize': truncated or malformed object (dataoff field plus datasize field of LC_DATA_IN_CODE command 0 extends past the end of the file) +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dyldinfo-small 2>&1 | FileCheck -check-prefix INVALID-DYLDINFO-SMALL %s +INVALID-DYLDINFO-SMALL: macho-invalid-dyldinfo-small': truncated or malformed object (load command 0 LC_DYLD_INFO cmdsize too small) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dyldinfoonly-bad-size 2>&1 | FileCheck -check-prefix INVALID-DYLDINFOONLY-BAD-SIZE %s +INVALID-DYLDINFOONLY-BAD-SIZE: macho-invalid-dyldinfoonly-bad-size': truncated or malformed object (LC_DYLD_INFO_ONLY command 0 has incorrect cmdsize) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dyldinfo-rebase_off 2>&1 | FileCheck -check-prefix INVALID-DYLDINFO-REBASE_OFF %s +INVALID-DYLDINFO-REBASE_OFF: macho-invalid-dyldinfo-rebase_off': truncated or malformed object (rebase_off field of LC_DYLD_INFO command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dyldinfo-rebase_off-rebase_size 2>&1 | FileCheck -check-prefix INVALID-DYLDINFO-REBASE_OFF-REBASE_SIZE %s +INVALID-DYLDINFO-REBASE_OFF-REBASE_SIZE: macho-invalid-dyldinfo-rebase_off-rebase_size': truncated or malformed object (rebase_off field plus rebase_size field of LC_DYLD_INFO command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dyldinfoonly-bind_off 2>&1 | FileCheck -check-prefix INVALID-DYLDINFOONLY-BIND_OFF %s +INVALID-DYLDINFOONLY-BIND_OFF: macho-invalid-dyldinfoonly-bind_off': truncated or malformed object (bind_off field of LC_DYLD_INFO_ONLY command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dyldinfo-bind_off-bind_size 2>&1 | FileCheck -check-prefix INVALID-DYLDINFO-BIND_OFF-BIND_SIZE %s +INVALID-DYLDINFO-BIND_OFF-BIND_SIZE: macho-invalid-dyldinfo-bind_off-bind_size': truncated or malformed object (bind_off field plus bind_size field of LC_DYLD_INFO command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dyldinfoonly-weak_bind_off 2>&1 | FileCheck -check-prefix INVALID-DYLDINFOONLY-WEAK_BIND_OFF %s +INVALID-DYLDINFOONLY-WEAK_BIND_OFF: macho-invalid-dyldinfoonly-weak_bind_off': truncated or malformed object (weak_bind_off field of LC_DYLD_INFO_ONLY command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dyldinfo-weak_bind_off-weak_bind_size 2>&1 | FileCheck -check-prefix INVALID-DYLDINFO-WEAK_BIND_OFF-WEAK_BIND_SIZE %s +INVALID-DYLDINFO-WEAK_BIND_OFF-WEAK_BIND_SIZE: macho-invalid-dyldinfo-weak_bind_off-weak_bind_size': truncated or malformed object (weak_bind_off field plus weak_bind_size field of LC_DYLD_INFO command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dyldinfoonly-lazy_bind_off 2>&1 | FileCheck -check-prefix INVALID-DYLDINFOONLY-LAZY_BIND_OFF %s +INVALID-DYLDINFOONLY-LAZY_BIND_OFF: macho-invalid-dyldinfoonly-lazy_bind_off': truncated or malformed object (lazy_bind_off field of LC_DYLD_INFO_ONLY command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dyldinfo-lazy_bind_off-lazy_bind_size 2>&1 | FileCheck -check-prefix INVALID-DYLDINFO-LAZY_BIND_OFF-LAZY_BIND_SIZE %s +INVALID-DYLDINFO-LAZY_BIND_OFF-LAZY_BIND_SIZE: macho-invalid-dyldinfo-lazy_bind_off-lazy_bind_size': truncated or malformed object (lazy_bind_off field plus lazy_bind_size field of LC_DYLD_INFO command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dyldinfoonly-export_off 2>&1 | FileCheck -check-prefix INVALID-DYLDINFOONLY-EXPORT_OFF %s +INVALID-DYLDINFOONLY-EXPORT_OFF: macho-invalid-dyldinfoonly-export_off': truncated or malformed object (export_off field of LC_DYLD_INFO_ONLY command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dyldinfo-export_off-export_size 2>&1 | FileCheck -check-prefix INVALID-DYLDINFO-EXPORT_OFF-EXPORT_SIZE %s +INVALID-DYLDINFO-EXPORT_OFF-EXPORT_SIZE: macho-invalid-dyldinfo-export_off-export_size': truncated or malformed object (export_off field plus export_size field of LC_DYLD_INFO command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dyldinfo-more-than-one 2>&1 | FileCheck -check-prefix INVALID-DYLDINFO-MORE-THAN-ONE %s +INVALID-DYLDINFO-MORE-THAN-ONE: macho-invalid-dyldinfo-more-than-one': truncated or malformed object (more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY command) |