summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Object/MachOObjectFile.cpp54
-rw-r--r--llvm/test/Object/Inputs/macho-invalid-bad-symbol-indexbin0 -> 4536 bytes
-rw-r--r--llvm/test/Object/Inputs/macho-invalid-getsection-indexbin0 -> 316 bytes
-rw-r--r--llvm/test/Object/Inputs/macho-invalid-no-size-for-sectionsbin0 -> 104 bytes
-rw-r--r--llvm/test/Object/Inputs/macho-invalid-section-index-getSectionRawFinalSegmentNamebin0 -> 4536 bytes
-rw-r--r--llvm/test/Object/Inputs/macho-invalid-section-index-getSectionRawNamebin0 -> 4536 bytes
-rw-r--r--llvm/test/Object/Inputs/macho-invalid-symbol-name-past-eofbin0 -> 4536 bytes
-rw-r--r--llvm/test/Object/Inputs/macho-invalid-too-small-load-commandbin0 -> 36 bytes
-rw-r--r--llvm/test/Object/Inputs/macho-invalid-too-small-segment-load-commandbin0 -> 104 bytes
-rw-r--r--llvm/test/Object/Inputs/macho-invalid-zero-ncmds (renamed from llvm/test/Object/Inputs/macho-zero-ncmds)bin32 -> 32 bytes
-rw-r--r--llvm/test/Object/Inputs/macho64-invalid-getsection-indexbin0 -> 4536 bytes
-rw-r--r--llvm/test/Object/Inputs/macho64-invalid-incomplete-load-commandbin0 -> 36 bytes
-rw-r--r--llvm/test/Object/Inputs/macho64-invalid-no-size-for-sectionsbin0 -> 104 bytes
-rw-r--r--llvm/test/Object/Inputs/macho64-invalid-too-small-load-commandbin0 -> 40 bytes
-rw-r--r--llvm/test/Object/Inputs/macho64-invalid-too-small-segment-load-commandbin0 -> 104 bytes
-rw-r--r--llvm/test/Object/macho-invalid.test51
-rw-r--r--llvm/test/Object/objdump-macho-quirks.test9
17 files changed, 97 insertions, 17 deletions
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index 978988c2569..a367a49f6bc 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -38,8 +38,12 @@ namespace {
};
}
-template<typename T>
+template <typename T>
static T getStruct(const MachOObjectFile *O, const char *P) {
+ // Don't read before the beginning or past the end of the file
+ if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
+ report_fatal_error("Malformed MachO file.");
+
T Cmd;
memcpy(&Cmd, P, sizeof(T));
if (O->isLittleEndian() != sys::IsLittleEndianHost)
@@ -47,15 +51,26 @@ static T getStruct(const MachOObjectFile *O, const char *P) {
return Cmd;
}
+template <typename SegmentCmd>
+static uint32_t getSegmentLoadCommandNumSections(const SegmentCmd &S,
+ uint32_t Cmdsize) {
+ const unsigned SectionSize = sizeof(SegmentCmd);
+ if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
+ S.nsects * SectionSize > Cmdsize - sizeof(S))
+ report_fatal_error(
+ "Number of sections too large for size of load command.");
+ return S.nsects;
+}
+
static uint32_t
getSegmentLoadCommandNumSections(const MachOObjectFile *O,
const MachOObjectFile::LoadCommandInfo &L) {
- if (O->is64Bit()) {
- MachO::segment_command_64 S = O->getSegment64LoadCommand(L);
- return S.nsects;
- }
- MachO::segment_command S = O->getSegmentLoadCommand(L);
- return S.nsects;
+ if (O->is64Bit())
+ return getSegmentLoadCommandNumSections(O->getSegment64LoadCommand(L),
+ L.C.cmdsize);
+
+ return getSegmentLoadCommandNumSections(O->getSegmentLoadCommand(L),
+ L.C.cmdsize);
}
static bool isPageZeroSegment(const MachOObjectFile *O,
@@ -281,6 +296,12 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
}
UuidLoadCmd = Load.Ptr;
} else if (Load.C.cmd == SegmentLoadType) {
+ const unsigned SegmentLoadSize = this->is64Bit()
+ ? sizeof(MachO::segment_command_64)
+ : sizeof(MachO::segment_command);
+ if (Load.C.cmdsize < SegmentLoadSize)
+ report_fatal_error("Segment load command size is too small.");
+
uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);
for (unsigned J = 0; J < NumSections; ++J) {
const char *Sec = getSectionPtr(this, Load, J);
@@ -315,6 +336,8 @@ std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb,
StringRef StringTable = getStringTableData();
MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);
const char *Start = &StringTable.data()[Entry.n_strx];
+ if (Start >= getData().end())
+ report_fatal_error("Symbol name entry points past end of file.");
Res = StringRef(Start);
return object_error::success;
}
@@ -1204,7 +1227,8 @@ basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
return basic_symbol_iterator(SymbolRef(DRI, this));
MachO::symtab_command Symtab = getSymtabLoadCommand();
- assert(Index < Symtab.nsyms && "Requested symbol index is out of range.");
+ if (Index >= Symtab.nsyms)
+ report_fatal_error("Requested symbol index is out of range.");
unsigned SymbolTableEntrySize =
is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff));
@@ -2108,6 +2132,8 @@ MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {
ArrayRef<char>
MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
+ if (Sec.d.a >= Sections.size())
+ report_fatal_error("getSectionRawName: Invalid section index");
const section_base *Base =
reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
return makeArrayRef(Base->sectname);
@@ -2115,6 +2141,8 @@ MachOObjectFile::getSectionRawName(DataRefImpl Sec) const {
ArrayRef<char>
MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const {
+ if (Sec.d.a >= Sections.size())
+ report_fatal_error("getSectionRawFinalSegmentName: Invalid section index");
const section_base *Base =
reinterpret_cast<const section_base *>(Sections[Sec.d.a]);
return makeArrayRef(Base->segname);
@@ -2205,6 +2233,8 @@ MachOObjectFile::getFirstLoadCommandInfo() const {
sizeof(MachO::mach_header);
Load.Ptr = getPtr(this, HeaderSize);
Load.C = getStruct<MachO::load_command>(this, Load.Ptr);
+ if (Load.C.cmdsize < 8)
+ report_fatal_error("Load command with size < 8 bytes.");
return Load;
}
@@ -2213,14 +2243,22 @@ MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const {
MachOObjectFile::LoadCommandInfo Next;
Next.Ptr = L.Ptr + L.C.cmdsize;
Next.C = getStruct<MachO::load_command>(this, Next.Ptr);
+ if (Next.C.cmdsize < 8)
+ report_fatal_error("Load command with size < 8 bytes.");
return Next;
}
MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const {
+ // TODO: What if Sections.size() == 0?
+ if (DRI.d.a >= Sections.size())
+ report_fatal_error("getSection: Invalid section index.");
return getStruct<MachO::section>(this, Sections[DRI.d.a]);
}
MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const {
+ // TODO: What if Sections.size() == 0?
+ if (DRI.d.a >= Sections.size())
+ report_fatal_error("getSection64: Invalid section index.");
return getStruct<MachO::section_64>(this, Sections[DRI.d.a]);
}
diff --git a/llvm/test/Object/Inputs/macho-invalid-bad-symbol-index b/llvm/test/Object/Inputs/macho-invalid-bad-symbol-index
new file mode 100644
index 00000000000..294bbde3ddf
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho-invalid-bad-symbol-index
Binary files differ
diff --git a/llvm/test/Object/Inputs/macho-invalid-getsection-index b/llvm/test/Object/Inputs/macho-invalid-getsection-index
new file mode 100644
index 00000000000..b7e4b95bc9b
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho-invalid-getsection-index
Binary files differ
diff --git a/llvm/test/Object/Inputs/macho-invalid-no-size-for-sections b/llvm/test/Object/Inputs/macho-invalid-no-size-for-sections
new file mode 100644
index 00000000000..89fa95acbcf
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho-invalid-no-size-for-sections
Binary files differ
diff --git a/llvm/test/Object/Inputs/macho-invalid-section-index-getSectionRawFinalSegmentName b/llvm/test/Object/Inputs/macho-invalid-section-index-getSectionRawFinalSegmentName
new file mode 100644
index 00000000000..e3f65865922
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho-invalid-section-index-getSectionRawFinalSegmentName
Binary files differ
diff --git a/llvm/test/Object/Inputs/macho-invalid-section-index-getSectionRawName b/llvm/test/Object/Inputs/macho-invalid-section-index-getSectionRawName
new file mode 100644
index 00000000000..9cd3e1cace8
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho-invalid-section-index-getSectionRawName
Binary files differ
diff --git a/llvm/test/Object/Inputs/macho-invalid-symbol-name-past-eof b/llvm/test/Object/Inputs/macho-invalid-symbol-name-past-eof
new file mode 100644
index 00000000000..87478840787
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho-invalid-symbol-name-past-eof
Binary files differ
diff --git a/llvm/test/Object/Inputs/macho-invalid-too-small-load-command b/llvm/test/Object/Inputs/macho-invalid-too-small-load-command
new file mode 100644
index 00000000000..36021692ee5
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho-invalid-too-small-load-command
Binary files differ
diff --git a/llvm/test/Object/Inputs/macho-invalid-too-small-segment-load-command b/llvm/test/Object/Inputs/macho-invalid-too-small-segment-load-command
new file mode 100644
index 00000000000..8cbfbf96578
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho-invalid-too-small-segment-load-command
Binary files differ
diff --git a/llvm/test/Object/Inputs/macho-zero-ncmds b/llvm/test/Object/Inputs/macho-invalid-zero-ncmds
index 0505419195e..0505419195e 100644
--- a/llvm/test/Object/Inputs/macho-zero-ncmds
+++ b/llvm/test/Object/Inputs/macho-invalid-zero-ncmds
Binary files differ
diff --git a/llvm/test/Object/Inputs/macho64-invalid-getsection-index b/llvm/test/Object/Inputs/macho64-invalid-getsection-index
new file mode 100644
index 00000000000..a2a7bc10c4f
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho64-invalid-getsection-index
Binary files differ
diff --git a/llvm/test/Object/Inputs/macho64-invalid-incomplete-load-command b/llvm/test/Object/Inputs/macho64-invalid-incomplete-load-command
new file mode 100644
index 00000000000..a569c9e14b3
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho64-invalid-incomplete-load-command
Binary files differ
diff --git a/llvm/test/Object/Inputs/macho64-invalid-no-size-for-sections b/llvm/test/Object/Inputs/macho64-invalid-no-size-for-sections
new file mode 100644
index 00000000000..5aae5ffed3a
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho64-invalid-no-size-for-sections
Binary files differ
diff --git a/llvm/test/Object/Inputs/macho64-invalid-too-small-load-command b/llvm/test/Object/Inputs/macho64-invalid-too-small-load-command
new file mode 100644
index 00000000000..0028451d190
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho64-invalid-too-small-load-command
Binary files differ
diff --git a/llvm/test/Object/Inputs/macho64-invalid-too-small-segment-load-command b/llvm/test/Object/Inputs/macho64-invalid-too-small-segment-load-command
new file mode 100644
index 00000000000..ce6a20134a9
--- /dev/null
+++ b/llvm/test/Object/Inputs/macho64-invalid-too-small-segment-load-command
Binary files differ
diff --git a/llvm/test/Object/macho-invalid.test b/llvm/test/Object/macho-invalid.test
new file mode 100644
index 00000000000..138d8eb1f3d
--- /dev/null
+++ b/llvm/test/Object/macho-invalid.test
@@ -0,0 +1,51 @@
+// No crash, might not be totally invalid
+RUN: llvm-objdump -private-headers %p/Inputs/macho-invalid-zero-ncmds
+
+RUN: not llvm-objdump -private-headers %p/Inputs/macho64-invalid-incomplete-load-command 2>&1 \
+RUN: | FileCheck -check-prefix INCOMPLETE-LOADC %s
+
+RUN: not llvm-objdump -private-headers %p/Inputs/macho-invalid-too-small-load-command 2>&1 \
+RUN: | FileCheck -check-prefix SMALL-LOADC-SIZE %s
+RUN: not llvm-objdump -private-headers %p/Inputs/macho64-invalid-too-small-load-command 2>&1 \
+RUN: | FileCheck -check-prefix SMALL-LOADC-SIZE %s
+
+RUN: not llvm-objdump -private-headers %p/Inputs/macho-invalid-too-small-segment-load-command 2>&1 \
+RUN: | FileCheck -check-prefix SMALL-SEGLOADC-SIZE %s
+RUN: not llvm-objdump -private-headers %p/Inputs/macho64-invalid-too-small-segment-load-command 2>&1 \
+RUN: | FileCheck -check-prefix SMALL-SEGLOADC-SIZE %s
+
+RUN: not llvm-objdump -private-headers %p/Inputs/macho-invalid-no-size-for-sections 2>&1 \
+RUN: | FileCheck -check-prefix TOO-MANY-SECTS %s
+RUN: not llvm-objdump -private-headers %p/Inputs/macho64-invalid-no-size-for-sections 2>&1 \
+RUN: | FileCheck -check-prefix TOO-MANY-SECTS %s
+
+RUN: not llvm-objdump -t %p/Inputs/macho-invalid-bad-symbol-index 2>&1 \
+RUN: | FileCheck -check-prefix BAD-SYMBOL %s
+
+RUN: not llvm-objdump -t %p/Inputs/macho-invalid-symbol-name-past-eof 2>&1 \
+RUN: | FileCheck -check-prefix NAME-PAST-EOF %s
+
+RUN: not llvm-objdump -t %p/Inputs/macho-invalid-section-index-getSectionRawFinalSegmentName 2>&1 \
+RUN: | FileCheck -check-prefix INVALID-SECTION-IDX-SEG-NAME %s
+
+RUN: not llvm-nm %p/Inputs/macho-invalid-section-index-getSectionRawName 2>&1 \
+RUN: | FileCheck -check-prefix INVALID-SECTION-IDX-SECT-NAME %s
+
+RUN: not llvm-objdump -t %p/Inputs/macho-invalid-getsection-index 2>&1 \
+RUN: | FileCheck -check-prefix INVALID-SECTION-IDX-GETSECT %s
+
+RUN: not llvm-objdump -t %p/Inputs/macho64-invalid-getsection-index 2>&1 \
+RUN: | FileCheck -check-prefix INVALID-SECTION-IDX-GETSECT64 %s
+
+
+SMALL-LOADC-SIZE: Load command with size < 8 bytes
+SMALL-SEGLOADC-SIZE: Segment load command size is too small
+INCOMPLETE-LOADC: Malformed MachO file
+TOO-MANY-SECTS: Number of sections too large for size of load command
+BAD-SYMBOL: Requested symbol index is out of range
+NAME-PAST-EOF: Symbol name entry points past end of file
+
+INVALID-SECTION-IDX-SEG-NAME: getSectionRawFinalSegmentName: Invalid section index
+INVALID-SECTION-IDX-SECT-NAME: getSectionRawName: Invalid section index
+INVALID-SECTION-IDX-GETSECT: getSection: Invalid section index
+INVALID-SECTION-IDX-GETSECT64: getSection64: Invalid section index
diff --git a/llvm/test/Object/objdump-macho-quirks.test b/llvm/test/Object/objdump-macho-quirks.test
deleted file mode 100644
index eeee1537def..00000000000
--- a/llvm/test/Object/objdump-macho-quirks.test
+++ /dev/null
@@ -1,9 +0,0 @@
-RUN: llvm-objdump -private-headers %p/Inputs/macho-zero-ncmds \
-RUN: | FileCheck %s -check-prefix A
-
-// Check that we don't get an infinite loop if ncmds = 0
-A: file format Mach-O 64-bit unknown
-A: Mach header
-A: magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
-A: MH_MAGIC_64 0x00 OBJECT 0 0 0x00000000
-
OpenPOWER on IntegriCloud