diff options
-rw-r--r-- | llvm/include/llvm/Object/MachO.h | 2 | ||||
-rw-r--r-- | llvm/lib/Object/MachOObjectFile.cpp | 68 | ||||
-rw-r--r-- | llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-indr | bin | 0 -> 260 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-lib_ordinal | bin | 0 -> 304 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-nsect | bin | 0 -> 424 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-strx | bin | 0 -> 260 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-objdump/X86/malformed-machos.test | 12 | ||||
-rw-r--r-- | llvm/tools/llvm-objdump/MachODump.cpp | 3 |
8 files changed, 85 insertions, 0 deletions
diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h index a26a2ef7dfe..b0f106f89c0 100644 --- a/llvm/include/llvm/Object/MachO.h +++ b/llvm/include/llvm/Object/MachO.h @@ -203,6 +203,8 @@ public: Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; // MachO specific. + Error checkSymbolTable() const; + std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; unsigned getSectionType(SectionRef Sec) const; diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp index 6650ace0845..cd0c2006f00 100644 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -1501,6 +1501,74 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, Err = Error::success(); } +Error MachOObjectFile::checkSymbolTable() const { + uint32_t Flags = 0; + if (is64Bit()) { + MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64(); + Flags = H_64.flags; + } else { + MachO::mach_header H = MachOObjectFile::getHeader(); + Flags = H.flags; + } + uint8_t NType = 0; + uint8_t NSect = 0; + uint16_t NDesc = 0; + uint32_t NStrx = 0; + uint64_t NValue = 0; + uint32_t SymbolIndex = 0; + MachO::symtab_command S = getSymtabLoadCommand(); + for (const SymbolRef &Symbol : symbols()) { + DataRefImpl SymDRI = Symbol.getRawDataRefImpl(); + if (is64Bit()) { + MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI); + NType = STE_64.n_type; + NSect = STE_64.n_sect; + NDesc = STE_64.n_desc; + NStrx = STE_64.n_strx; + NValue = STE_64.n_value; + } else { + MachO::nlist STE = getSymbolTableEntry(SymDRI); + NType = STE.n_type; + NType = STE.n_type; + NSect = STE.n_sect; + NDesc = STE.n_desc; + NStrx = STE.n_strx; + NValue = STE.n_value; + } + if ((NType & MachO::N_STAB) == 0 && + (NType & MachO::N_TYPE) == MachO::N_SECT) { + if (NSect == 0 || NSect > Sections.size()) + return malformedError("bad section index: " + Twine((int)NSect) + + " for symbol at index " + Twine(SymbolIndex)); + } + if ((NType & MachO::N_STAB) == 0 && + (NType & MachO::N_TYPE) == MachO::N_INDR) { + if (NValue >= S.strsize) + return malformedError("bad n_value: " + Twine((int)NValue) + " past " + "the end of string table, for N_INDR symbol at " + "index " + Twine(SymbolIndex)); + } + if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL && + (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) || + (NType & MachO::N_TYPE) == MachO::N_PBUD)) { + uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc); + if (LibraryOrdinal != 0 && + LibraryOrdinal != MachO::EXECUTABLE_ORDINAL && + LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL && + LibraryOrdinal - 1 >= Libraries.size() ) { + return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) + + " for symbol at index " + Twine(SymbolIndex)); + } + } + if (NStrx >= S.strsize) + return malformedError("bad string table index: " + Twine((int)NStrx) + + " past the end of string table, for symbol at " + "index " + Twine(SymbolIndex)); + SymbolIndex++; + } + return Error::success(); +} + void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { unsigned SymbolTableEntrySize = is64Bit() ? sizeof(MachO::nlist_64) : diff --git a/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-indr b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-indr Binary files differnew file mode 100644 index 00000000000..67751b7f12e --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-indr diff --git a/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-lib_ordinal b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-lib_ordinal Binary files differnew file mode 100644 index 00000000000..d3b54701a55 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-lib_ordinal diff --git a/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-nsect b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-nsect Binary files differnew file mode 100644 index 00000000000..3ee21c4b024 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-nsect diff --git a/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-strx b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-strx Binary files differnew file mode 100644 index 00000000000..4a6e56135db --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-strx diff --git a/llvm/test/tools/llvm-objdump/X86/malformed-machos.test b/llvm/test/tools/llvm-objdump/X86/malformed-machos.test index 499c23e09d2..edd6a24177e 100644 --- a/llvm/test/tools/llvm-objdump/X86/malformed-machos.test +++ b/llvm/test/tools/llvm-objdump/X86/malformed-machos.test @@ -39,3 +39,15 @@ # RUN: | FileCheck -check-prefix=m0337 %s # m0337: mem-crup-0337.macho': truncated or malformed object (section relocation entries at offset 0 with a size of 512, overlaps Mach-O headers at offset 0 with a size of 2048) + +RUN: not llvm-objdump -macho -disassemble %p/Inputs/macho-invalid-symbol-nsect 2>&1 | FileCheck -check-prefix INVALID-SYMBOL-NSECT %s +INVALID-SYMBOL-NSECT: macho-invalid-symbol-nsect': truncated or malformed object (bad section index: 97 for symbol at index 1) + +RUN: not llvm-objdump -macho -disassemble %p/Inputs/macho-invalid-symbol-indr 2>&1 | FileCheck -check-prefix INVALID-SYMBOL-INDR %s +INVALID-SYMBOL-INDR: macho-invalid-symbol-indr': truncated or malformed object (bad n_value: 22 past the end of string table, for N_INDR symbol at index 1) + +RUN: not llvm-objdump -macho -disassemble %p/Inputs/macho-invalid-symbol-strx 2>&1 | FileCheck -check-prefix INVALID-SYMBOL-STRX %s +INVALID-SYMBOL-STRX: macho-invalid-symbol-strx': truncated or malformed object (bad string table index: 22 past the end of string table, for symbol at index 1) + +RUN: not llvm-objdump -macho -disassemble %p/Inputs/macho-invalid-symbol-lib_ordinal 2>&1 | FileCheck -check-prefix INVALID-SYMBOL-LIB_ORDINAL %s +INVALID-SYMBOL-LIB_ORDINAL: macho-invalid-symbol-lib_ordinal': truncated or malformed object (bad library ordinal: 7 for symbol at index 2) diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp index 929e70d8cb5..249ab7e90a3 100644 --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/tools/llvm-objdump/MachODump.cpp @@ -6523,6 +6523,9 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, SmallVector<uint64_t, 8> FoundFns; uint64_t BaseSegmentAddress; + if (Error Err = MachOOF->checkSymbolTable()) + report_error(Filename, std::move(Err)); + getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns, BaseSegmentAddress); |