summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Object/MachO.h2
-rw-r--r--llvm/lib/Object/MachOObjectFile.cpp68
-rw-r--r--llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-indrbin0 -> 260 bytes
-rw-r--r--llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-lib_ordinalbin0 -> 304 bytes
-rw-r--r--llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-nsectbin0 -> 424 bytes
-rw-r--r--llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-strxbin0 -> 260 bytes
-rw-r--r--llvm/test/tools/llvm-objdump/X86/malformed-machos.test12
-rw-r--r--llvm/tools/llvm-objdump/MachODump.cpp3
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
new file mode 100644
index 00000000000..67751b7f12e
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-indr
Binary files differ
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
new file mode 100644
index 00000000000..d3b54701a55
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-lib_ordinal
Binary files differ
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
new file mode 100644
index 00000000000..3ee21c4b024
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-nsect
Binary files differ
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
new file mode 100644
index 00000000000..4a6e56135db
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/X86/Inputs/macho-invalid-symbol-strx
Binary files differ
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);
OpenPOWER on IntegriCloud