diff options
Diffstat (limited to 'llvm')
16 files changed, 144 insertions, 6 deletions
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp index 26fd9a68724..b5ca95add73 100644 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -372,11 +372,108 @@ static Error checkSymtabCommand(const MachOObjectFile *Obj, return malformedError("stroff field plus strsize field of LC_SYMTAB " "command " + Twine(LoadCommandIndex) + " extends " "past the end of the file"); - *SymtabLoadCmd = Load.Ptr; return Error::success(); } +static Error checkDysymtabCommand(const MachOObjectFile *Obj, + const MachOObjectFile::LoadCommandInfo &Load, + uint32_t LoadCommandIndex, + const char **DysymtabLoadCmd) { + if (Load.C.cmdsize < sizeof(MachO::dysymtab_command)) + return malformedError("load command " + Twine(LoadCommandIndex) + + " LC_DYSYMTAB cmdsize too small"); + if (*DysymtabLoadCmd != nullptr) + return malformedError("more than one LC_DYSYMTAB command"); + MachO::dysymtab_command Dysymtab = + getStruct<MachO::dysymtab_command>(Obj, Load.Ptr); + if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command)) + return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) + + " has incorrect cmdsize"); + uint64_t FileSize = Obj->getData().size(); + if (Dysymtab.tocoff > FileSize) + return malformedError("tocoff field of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + uint64_t BigSize = Dysymtab.ntoc; + BigSize *= sizeof(MachO::dylib_table_of_contents); + BigSize += Dysymtab.tocoff; + if (BigSize > FileSize) + return malformedError("tocoff field plus ntoc field times sizeof(struct " + "dylib_table_of_contents) of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + if (Dysymtab.modtaboff > FileSize) + return malformedError("modtaboff field of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + BigSize = Dysymtab.nmodtab; + const char *struct_dylib_module_name; + if (Obj->is64Bit()) { + BigSize *= sizeof(MachO::dylib_module_64); + struct_dylib_module_name = "struct dylib_module_64"; + } else { + BigSize *= sizeof(MachO::dylib_module); + struct_dylib_module_name = "struct dylib_module"; + } + BigSize += Dysymtab.modtaboff; + if (BigSize > FileSize) + return malformedError("modtaboff field plus nmodtab field times sizeof(" + + Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB " + "command " + Twine(LoadCommandIndex) + " extends " + "past the end of the file"); + if (Dysymtab.extrefsymoff > FileSize) + return malformedError("extrefsymoff field of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + BigSize = Dysymtab.nextrefsyms; + BigSize *= sizeof(MachO::dylib_reference); + BigSize += Dysymtab.extrefsymoff; + if (BigSize > FileSize) + return malformedError("extrefsymoff field plus nextrefsyms field times " + "sizeof(struct dylib_reference) of LC_DYSYMTAB " + "command " + Twine(LoadCommandIndex) + " extends " + "past the end of the file"); + if (Dysymtab.indirectsymoff > FileSize) + return malformedError("indirectsymoff field of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + BigSize = Dysymtab.nindirectsyms; + BigSize *= sizeof(uint32_t); + BigSize += Dysymtab.indirectsymoff; + if (BigSize > FileSize) + return malformedError("indirectsymoff field plus nindirectsyms field times " + "sizeof(uint32_t) of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + if (Dysymtab.extreloff > FileSize) + return malformedError("extreloff field of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + BigSize = Dysymtab.nextrel; + BigSize *= sizeof(MachO::relocation_info); + BigSize += Dysymtab.extreloff; + if (BigSize > FileSize) + return malformedError("extreloff field plus nextrel field times sizeof" + "(struct relocation_info) of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + if (Dysymtab.locreloff > FileSize) + return malformedError("locreloff field of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + BigSize = Dysymtab.nlocrel; + BigSize *= sizeof(MachO::relocation_info); + BigSize += Dysymtab.locreloff; + if (BigSize > FileSize) + return malformedError("locreloff field plus nlocrel field times sizeof" + "(struct relocation_info) of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + *DysymtabLoadCmd = Load.Ptr; + return Error::success(); +} + Expected<std::unique_ptr<MachOObjectFile>> MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits) { @@ -450,12 +547,8 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd))) return; } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { - // Multiple dynamic symbol tables - if (DysymtabLoadCmd) { - Err = malformedError("Multiple dynamic symbol tables"); + if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd))) return; - } - DysymtabLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { // Multiple data in code tables if (DataInCodeLoadCmd) { diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-bad-size b/llvm/test/Object/Inputs/macho-invalid-dysymtab-bad-size Binary files differnew file mode 100644 index 00000000000..49065d6334f --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-bad-size diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-extrefsymoff b/llvm/test/Object/Inputs/macho-invalid-dysymtab-extrefsymoff Binary files differnew file mode 100644 index 00000000000..0e80fba0f23 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-extrefsymoff diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-extrefsymoff-nextrefsyms b/llvm/test/Object/Inputs/macho-invalid-dysymtab-extrefsymoff-nextrefsyms Binary files differnew file mode 100644 index 00000000000..f08b1330241 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-extrefsymoff-nextrefsyms diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-extreloff b/llvm/test/Object/Inputs/macho-invalid-dysymtab-extreloff Binary files differnew file mode 100644 index 00000000000..d04eccaed8f --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-extreloff diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-indirectsymoff b/llvm/test/Object/Inputs/macho-invalid-dysymtab-indirectsymoff Binary files differnew file mode 100644 index 00000000000..46d94780b44 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-indirectsymoff diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-indirectsymoff-nindirectsyms b/llvm/test/Object/Inputs/macho-invalid-dysymtab-indirectsymoff-nindirectsyms Binary files differnew file mode 100644 index 00000000000..9c4b3b3781c --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-indirectsymoff-nindirectsyms diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-locreloff b/llvm/test/Object/Inputs/macho-invalid-dysymtab-locreloff Binary files differnew file mode 100644 index 00000000000..0ddab0c3b87 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-locreloff diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-locreloff-nlocrel b/llvm/test/Object/Inputs/macho-invalid-dysymtab-locreloff-nlocrel Binary files differnew file mode 100644 index 00000000000..94f4b2d3f86 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-locreloff-nlocrel diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-modtaboff b/llvm/test/Object/Inputs/macho-invalid-dysymtab-modtaboff Binary files differnew file mode 100644 index 00000000000..c8e80ac2105 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-modtaboff diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-modtaboff-nmodtab b/llvm/test/Object/Inputs/macho-invalid-dysymtab-modtaboff-nmodtab Binary files differnew file mode 100644 index 00000000000..dd643ca0698 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-modtaboff-nmodtab diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-more-than-one b/llvm/test/Object/Inputs/macho-invalid-dysymtab-more-than-one Binary files differnew file mode 100644 index 00000000000..0a0f8593d22 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-more-than-one diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-small b/llvm/test/Object/Inputs/macho-invalid-dysymtab-small Binary files differnew file mode 100644 index 00000000000..53c61f9cc79 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-small diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-tocoff b/llvm/test/Object/Inputs/macho-invalid-dysymtab-tocoff Binary files differnew file mode 100644 index 00000000000..9a86fd84c21 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-tocoff diff --git a/llvm/test/Object/Inputs/macho-invalid-dysymtab-tocoff-ntoc b/llvm/test/Object/Inputs/macho-invalid-dysymtab-tocoff-ntoc Binary files differnew file mode 100644 index 00000000000..ec09e312863 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-dysymtab-tocoff-ntoc diff --git a/llvm/test/Object/macho-invalid.test b/llvm/test/Object/macho-invalid.test index c2f6ed20bf6..2162a88a52f 100644 --- a/llvm/test/Object/macho-invalid.test +++ b/llvm/test/Object/macho-invalid.test @@ -163,3 +163,48 @@ INVALID-SYMTAB-STROFF: macho-invalid-symtab-stroff': truncated or malformed obje RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-symtab-stroff-strsize 2>&1 | FileCheck -check-prefix INVALID-SYMTAB-STROFF-STRSIZE %s INVALID-SYMTAB-STROFF-STRSIZE: macho-invalid-symtab-stroff-strsize': truncated or malformed object (stroff field plus strsize field of LC_SYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-small 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-SMALL %s +INVALID-DYSYMTAB-SMALL: macho-invalid-dysymtab-small': truncated or malformed object (load command 0 LC_DYSYMTAB cmdsize too small) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-more-than-one 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-MORE-THAN-ONE %s +INVALID-DYSYMTAB-MORE-THAN-ONE: macho-invalid-dysymtab-more-than-one': truncated or malformed object (more than one LC_DYSYMTAB command) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-bad-size 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-BAD-SIZE %s +INVALID-DYSYMTAB-BAD-SIZE: macho-invalid-dysymtab-bad-size': truncated or malformed object (LC_DYSYMTAB command 0 has incorrect cmdsize) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-tocoff 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF %s +INVALID-DYSYMTAB-TOCOFF: macho-invalid-dysymtab-tocoff': truncated or malformed object (tocoff field of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-tocoff-ntoc 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-NTOC %s +INVALID-DYSYMTAB-TOCOFF-NTOC: macho-invalid-dysymtab-tocoff-ntoc': truncated or malformed object (tocoff field plus ntoc field times sizeof(struct dylib_table_of_contents) of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-modtaboff 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-MODTABOFF %s +INVALID-DYSYMTAB-TOCOFF-MODTABOFF: macho-invalid-dysymtab-modtaboff': truncated or malformed object (modtaboff field of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-modtaboff-nmodtab 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-MODTABOFF-NMODTAB %s +INVALID-DYSYMTAB-TOCOFF-MODTABOFF-NMODTAB: macho-invalid-dysymtab-modtaboff-nmodtab': truncated or malformed object (modtaboff field plus nmodtab field times sizeof(struct dylib_module) of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-extrefsymoff 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-EXTREFSYMOFF %s +INVALID-DYSYMTAB-TOCOFF-EXTREFSYMOFF: macho-invalid-dysymtab-extrefsymoff': truncated or malformed object (extrefsymoff field of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-extrefsymoff-nextrefsyms 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-EXTREFSYMOFF-NEXTREFSYMS %s +INVALID-DYSYMTAB-TOCOFF-EXTREFSYMOFF-NEXTREFSYMS: macho-invalid-dysymtab-extrefsymoff-nextrefsyms': truncated or malformed object (extrefsymoff field plus nextrefsyms field times sizeof(struct dylib_reference) of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-indirectsymoff 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-INDIRECTSYMOFF %s +INVALID-DYSYMTAB-TOCOFF-INDIRECTSYMOFF: macho-invalid-dysymtab-indirectsymoff': truncated or malformed object (indirectsymoff field of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-indirectsymoff-nindirectsyms 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-INDIRECTSYMOFF-NINDIRECTSYMS %s +INVALID-DYSYMTAB-TOCOFF-INDIRECTSYMOFF-NINDIRECTSYMS: macho-invalid-dysymtab-indirectsymoff-nindirectsyms': truncated or malformed object (indirectsymoff field plus nindirectsyms field times sizeof(uint32_t) of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-extreloff 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-EXTRELOFF %s +INVALID-DYSYMTAB-TOCOFF-EXTRELOFF: macho-invalid-dysymtab-extreloff': truncated or malformed object (extreloff field of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-extreloff-nextrel 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-EXTRELOFF-NEXTREL %s +INVALID-DYSYMTAB-TOCOFF-EXTRELOFF-NEXTREL: macho-invalid-dysymtab-extreloff-nextrel': truncated or malformed object (extreloff field plus nextrel field times sizeof(struct relocation_info) of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-locreloff 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-LOCRELOFF %s +INVALID-DYSYMTAB-TOCOFF-LOCRELOFF: macho-invalid-dysymtab-locreloff': truncated or malformed object (locreloff field of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-locreloff-nlocrel 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-LOCRELOFF-NLOCREL %s +INVALID-DYSYMTAB-TOCOFF-LOCRELOFF-NLOCREL: macho-invalid-dysymtab-locreloff-nlocrel': truncated or malformed object (locreloff field plus nlocrel field times sizeof(struct relocation_info) of LC_DYSYMTAB command 0 extends past the end of the file) |

