diff options
author | Kevin Enderby <enderby@apple.com> | 2016-10-20 20:10:30 +0000 |
---|---|---|
committer | Kevin Enderby <enderby@apple.com> | 2016-10-20 20:10:30 +0000 |
commit | c8bb42283ee6a118219593a2c98abc0974eb5dc4 (patch) | |
tree | c36e97a0770dee048074cc653cd776b11b4ac06f /llvm | |
parent | 613c00db88e0a206e1223e5be7dfeb9b4a868c7d (diff) | |
download | bcm5719-llvm-c8bb42283ee6a118219593a2c98abc0974eb5dc4.tar.gz bcm5719-llvm-c8bb42283ee6a118219593a2c98abc0974eb5dc4.zip |
Another additional error check for invalid Mach-O files for the
load commands that use the MachO::twolevel_hints_command type
which includes only the LC_TWOLEVEL_HINTS load command.
This is not used in llvm libObject code or in llvm tool code. But
does appear in one of the binary test files. While this load command is
obsolete it is easier to add code for it in libObject than edit or change
the binary test case.
llvm-svn: 284769
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Object/MachOObjectFile.cpp | 34 | ||||
-rw-r--r-- | llvm/test/Object/Inputs/macho-invalid-twolevelhints-bad-size | bin | 0 -> 48 bytes | |||
-rw-r--r-- | llvm/test/Object/Inputs/macho-invalid-twolevelhints-more-than-one | bin | 0 -> 60 bytes | |||
-rw-r--r-- | llvm/test/Object/Inputs/macho-invalid-twolevelhints-offset | bin | 0 -> 44 bytes | |||
-rw-r--r-- | llvm/test/Object/Inputs/macho-invalid-twolevelhints-offset-nhints | bin | 0 -> 44 bytes | |||
-rw-r--r-- | llvm/test/Object/macho-invalid.test | 12 |
6 files changed, 46 insertions, 0 deletions
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp index 87b19a1db94..0edc6a71633 100644 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -883,6 +883,35 @@ static Error checkThreadCommand(const MachOObjectFile *Obj, return Error::success(); } +static Error checkTwoLevelHintsCommand(const MachOObjectFile *Obj, + const MachOObjectFile::LoadCommandInfo + &Load, + uint32_t LoadCommandIndex, + const char **LoadCmd) { + if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command)) + return malformedError("load command " + Twine(LoadCommandIndex) + + " LC_TWOLEVEL_HINTS has incorrect cmdsize"); + if (*LoadCmd != nullptr) + return malformedError("more than one LC_TWOLEVEL_HINTS command"); + MachO::twolevel_hints_command Hints = + getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr); + uint64_t FileSize = Obj->getData().size(); + if (Hints.offset > FileSize) + return malformedError("offset field of LC_TWOLEVEL_HINTS command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + uint64_t BigSize = Hints.nhints; + BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint); + BigSize += Hints.offset; + if (BigSize > FileSize) + return malformedError("offset field plus nhints times sizeof(struct " + "twolevel_hint) field of LC_TWOLEVEL_HINTS 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) { @@ -941,6 +970,7 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, const char *EncryptLoadCmd = nullptr; const char *RoutinesLoadCmd = nullptr; const char *UnixThreadLoadCmd = nullptr; + const char *TwoLevelHintsLoadCmd = nullptr; for (unsigned I = 0; I < LoadCommandCount; ++I) { if (is64Bit()) { if (Load.C.cmdsize % 8 != 0) { @@ -1207,6 +1237,10 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, } else if (Load.C.cmd == MachO::LC_THREAD) { if ((Err = checkThreadCommand(this, Load, I, "LC_THREAD"))) return; + } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) { + if ((Err = checkTwoLevelHintsCommand(this, Load, I, + &TwoLevelHintsLoadCmd))) + return; } if (I < LoadCommandCount - 1) { if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load)) diff --git a/llvm/test/Object/Inputs/macho-invalid-twolevelhints-bad-size b/llvm/test/Object/Inputs/macho-invalid-twolevelhints-bad-size Binary files differnew file mode 100644 index 00000000000..a13a00e6d20 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-twolevelhints-bad-size diff --git a/llvm/test/Object/Inputs/macho-invalid-twolevelhints-more-than-one b/llvm/test/Object/Inputs/macho-invalid-twolevelhints-more-than-one Binary files differnew file mode 100644 index 00000000000..27e3a17561e --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-twolevelhints-more-than-one diff --git a/llvm/test/Object/Inputs/macho-invalid-twolevelhints-offset b/llvm/test/Object/Inputs/macho-invalid-twolevelhints-offset Binary files differnew file mode 100644 index 00000000000..f280f14b923 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-twolevelhints-offset diff --git a/llvm/test/Object/Inputs/macho-invalid-twolevelhints-offset-nhints b/llvm/test/Object/Inputs/macho-invalid-twolevelhints-offset-nhints Binary files differnew file mode 100644 index 00000000000..81bf6a11594 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-twolevelhints-offset-nhints diff --git a/llvm/test/Object/macho-invalid.test b/llvm/test/Object/macho-invalid.test index 111ba661c93..5a00d0def52 100644 --- a/llvm/test/Object/macho-invalid.test +++ b/llvm/test/Object/macho-invalid.test @@ -394,3 +394,15 @@ INVALID-THREAD-UNKNOWN-CPUTYPE: macho-invalid-thread-unknown-cputype': truncated RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-unixthread-more-than-one 2>&1 | FileCheck -check-prefix INVALID-UNIXTHREAD-MORE-THAN-ONE %s INVALID-UNIXTHREAD-MORE-THAN-ONE: macho-invalid-unixthread-more-than-one': truncated or malformed object (more than one LC_UNIXTHREAD command) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-twolevelhints-bad-size 2>&1 | FileCheck -check-prefix INVALID-TWOLEVELHINTS-BAD-SIZE %s +INVALID-TWOLEVELHINTS-BAD-SIZE: macho-invalid-twolevelhints-bad-size': truncated or malformed object (load command 0 LC_TWOLEVEL_HINTS has incorrect cmdsize) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-twolevelhints-more-than-one 2>&1 | FileCheck -check-prefix INVALID-TWOLEVELHINTS-MORE-THAN-ONE %s +INVALID-TWOLEVELHINTS-MORE-THAN-ONE: macho-invalid-twolevelhints-more-than-one': truncated or malformed object (more than one LC_TWOLEVEL_HINTS command) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-twolevelhints-offset 2>&1 | FileCheck -check-prefix INVALID-TWOLEVELHINTS-OFFSET %s +INVALID-TWOLEVELHINTS-OFFSET: macho-invalid-twolevelhints-offset': truncated or malformed object (offset field of LC_TWOLEVEL_HINTS command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-twolevelhints-offset-nhints 2>&1 | FileCheck -check-prefix INVALID-TWOLEVELHINTS-OFFSET-HNINTS %s +INVALID-TWOLEVELHINTS-OFFSET-HNINTS: macho-invalid-twolevelhints-offset-nhints': truncated or malformed object (offset field plus nhints times sizeof(struct twolevel_hint) field of LC_TWOLEVEL_HINTS command 0 extends past the end of the file) |