From ff19e2b684835e63d9741865958bcdcdaa6e52a1 Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Fri, 26 Aug 2016 19:34:07 +0000 Subject: [PATCH] =?utf8?q?Next=20set=20of=20additional=20error=20checks=20?= =?utf8?q?for=20invalid=20Mach-O=20files=20for=20bad=20LC=5FSYMTAB?= =?utf8?q?=E2=80=99s.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This contains the missing checks for LC_SYMTAB load command fields. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@279854 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 55 +++++++++++++++++++-- test/Object/Inputs/macho-invalid-symtab-bad-size | Bin 0 -> 56 bytes .../Inputs/macho-invalid-symtab-more-than-one | Bin 0 -> 76 bytes test/Object/Inputs/macho-invalid-symtab-small | Bin 0 -> 52 bytes test/Object/Inputs/macho-invalid-symtab-stroff | Bin 0 -> 52 bytes .../Inputs/macho-invalid-symtab-stroff-strsize | Bin 0 -> 52 bytes test/Object/Inputs/macho-invalid-symtab-symoff | Bin 0 -> 52 bytes .../Inputs/macho-invalid-symtab-symoff-nsyms | Bin 0 -> 52 bytes test/Object/macho-invalid.test | 21 ++++++++ 9 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 test/Object/Inputs/macho-invalid-symtab-bad-size create mode 100644 test/Object/Inputs/macho-invalid-symtab-more-than-one create mode 100644 test/Object/Inputs/macho-invalid-symtab-small create mode 100644 test/Object/Inputs/macho-invalid-symtab-stroff create mode 100644 test/Object/Inputs/macho-invalid-symtab-stroff-strsize create mode 100644 test/Object/Inputs/macho-invalid-symtab-symoff create mode 100644 test/Object/Inputs/macho-invalid-symtab-symoff-nsyms diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 43e76a9b404..26fd9a68724 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -328,6 +328,55 @@ static Error parseSegmentLoadCommand( return Error::success(); } +static Error checkSymtabCommand(const MachOObjectFile *Obj, + const MachOObjectFile::LoadCommandInfo &Load, + uint32_t LoadCommandIndex, + const char **SymtabLoadCmd) { + if (Load.C.cmdsize < sizeof(MachO::symtab_command)) + return malformedError("load command " + Twine(LoadCommandIndex) + + " LC_SYMTAB cmdsize too small"); + if (*SymtabLoadCmd != nullptr) + return malformedError("more than one LC_SYMTAB command"); + MachO::symtab_command Symtab = + getStruct(Obj, Load.Ptr); + if (Symtab.cmdsize != sizeof(MachO::symtab_command)) + return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) + + " has incorrect cmdsize"); + uint64_t FileSize = Obj->getData().size(); + if (Symtab.symoff > FileSize) + return malformedError("symoff field of LC_SYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end " + "of the file"); + uint64_t BigSize = Symtab.nsyms; + const char *struct_nlist_name; + if (Obj->is64Bit()) { + BigSize *= sizeof(MachO::nlist_64); + struct_nlist_name = "struct nlist_64"; + } else { + BigSize *= sizeof(MachO::nlist); + struct_nlist_name = "struct nlist"; + } + BigSize += Symtab.symoff; + if (BigSize > FileSize) + return malformedError("symoff field plus nsyms field times sizeof(" + + Twine(struct_nlist_name) + ") of LC_SYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end " + "of the file"); + if (Symtab.stroff > FileSize) + return malformedError("stroff field of LC_SYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end " + "of the file"); + BigSize = Symtab.stroff; + BigSize += Symtab.strsize; + if (BigSize > FileSize) + 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(); +} + Expected> MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits) { @@ -398,12 +447,8 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, } LoadCommands.push_back(Load); if (Load.C.cmd == MachO::LC_SYMTAB) { - // Multiple symbol tables - if (SymtabLoadCmd) { - Err = malformedError("Multiple symbol tables"); + if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd))) return; - } - SymtabLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { // Multiple dynamic symbol tables if (DysymtabLoadCmd) { diff --git a/test/Object/Inputs/macho-invalid-symtab-bad-size b/test/Object/Inputs/macho-invalid-symtab-bad-size new file mode 100644 index 0000000000000000000000000000000000000000..12b6b89eda45498bfd7f3a90f13b2e30ed0a0fba GIT binary patch literal 56 gcmX^2>+L^w1_lOZAZCPO86XV;Oh61{g9VTX0Me=h`Tzg` literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-symtab-more-than-one b/test/Object/Inputs/macho-invalid-symtab-more-than-one new file mode 100644 index 0000000000000000000000000000000000000000..34088bfcdcf0e19994dbdfa4f75895dd6388c039 GIT binary patch literal 76 jcmX^2>+L^w1_lOZAZ7$&CLlHdVh{kaCBQ6H0+%=dC_Mxv literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-symtab-small b/test/Object/Inputs/macho-invalid-symtab-small new file mode 100644 index 0000000000000000000000000000000000000000..cf2294d8771b5ba8f5892f5d2006b828e7cf5af1 GIT binary patch literal 52 fcmX^2>+L^w1_lOZAZCPO2_OvuOh7CGW}y-Q!J-51 literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-symtab-stroff b/test/Object/Inputs/macho-invalid-symtab-stroff new file mode 100644 index 0000000000000000000000000000000000000000..44f7761227ea61dcc7b4ccab125db03b19ace69d GIT binary patch literal 52 icmX^2>+L^w1_lOZAZCPO2_OvuOh61{gZK_00tf)Z@&qyf literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-symtab-stroff-strsize b/test/Object/Inputs/macho-invalid-symtab-stroff-strsize new file mode 100644 index 0000000000000000000000000000000000000000..ea577377c0758618c4ffbe00a26d60c368287dd1 GIT binary patch literal 52 jcmX^2>+L^w1_lOZAZCPO2_OvuOh61{gZL&uEDFQ`!{!7# literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-symtab-symoff b/test/Object/Inputs/macho-invalid-symtab-symoff new file mode 100644 index 0000000000000000000000000000000000000000..c8251ac74d9bc1709597410147fc6d12b4aecf82 GIT binary patch literal 52 hcmX^2>+L^w1_lOZAZCPO2_OvuOh61`+kiMo0070Z1TFvo literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-symtab-symoff-nsyms b/test/Object/Inputs/macho-invalid-symtab-symoff-nsyms new file mode 100644 index 0000000000000000000000000000000000000000..85d79e75226a133363d0ab380f0b60dcd0aec167 GIT binary patch literal 52 jcmX^2>+L^w1_lOZAZCPO2_OvuOh61`n*cE{5W@ff#m)pX literal 0 HcmV?d00001 diff --git a/test/Object/macho-invalid.test b/test/Object/macho-invalid.test index 91e1ea7b1a0..c2f6ed20bf6 100644 --- a/test/Object/macho-invalid.test +++ b/test/Object/macho-invalid.test @@ -142,3 +142,24 @@ INVALID-SECTION-RELOFF: macho-invalid-section-reloff': truncated or malformed ob RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-section-reloff-nrelocs 2>&1 | FileCheck -check-prefix INVALID-SECTION-RELOFF-NRELOCS %s INVALID-SECTION-RELOFF-NRELOCS: macho-invalid-section-reloff-nrelocs': truncated or malformed object (reloff field plus nreloc field times sizeof(struct relocation_info) of section 0 in LC_SEGMENT command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-symtab-small 2>&1 | FileCheck -check-prefix INVALID-SYMTAB-SMALL %s +INVALID-SYMTAB-SMALL: macho-invalid-symtab-small': truncated or malformed object (load command 0 LC_SYMTAB cmdsize too small) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-symtab-more-than-one 2>&1 | FileCheck -check-prefix INVALID-SYMTAB-MORE-THAN-ONE %s +INVALID-SYMTAB-MORE-THAN-ONE: macho-invalid-symtab-more-than-one': truncated or malformed object (more than one LC_SYMTAB command) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-symtab-bad-size 2>&1 | FileCheck -check-prefix INVALID-SYMTAB-BAD-SIZE %s +INVALID-SYMTAB-BAD-SIZE: macho-invalid-symtab-bad-size': truncated or malformed object (LC_SYMTAB command 0 has incorrect cmdsize) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-symtab-symoff 2>&1 | FileCheck -check-prefix INVALID-SYMTAB-SYMOFF %s +INVALID-SYMTAB-SYMOFF: macho-invalid-symtab-symoff': truncated or malformed object (symoff field of LC_SYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-symtab-symoff-nsyms 2>&1 | FileCheck -check-prefix INVALID-SYMTAB-SYMOFF-NSYMS %s +INVALID-SYMTAB-SYMOFF-NSYMS: macho-invalid-symtab-symoff-nsyms': truncated or malformed object (symoff field plus nsyms field times sizeof(struct nlist) of LC_SYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-symtab-stroff 2>&1 | FileCheck -check-prefix INVALID-SYMTAB-STROFF %s +INVALID-SYMTAB-STROFF: macho-invalid-symtab-stroff': truncated or malformed object (stroff field of LC_SYMTAB command 0 extends past the end of the file) + +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) -- 2.11.0