From: Kevin Enderby Date: Fri, 26 Aug 2016 19:34:07 +0000 (+0000) Subject: Next set of additional error checks for invalid Mach-O files for bad LC_SYMTAB’s. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0e52c92e22eeb7d5b99bc711c467a129154ade09;p=platform%2Fupstream%2Fllvm.git Next set of additional error checks for invalid Mach-O files for bad LC_SYMTAB’s. This contains the missing checks for LC_SYMTAB load command fields. llvm-svn: 279854 --- diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp index 43e76a9..26fd9a6 100644 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/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/llvm/test/Object/Inputs/macho-invalid-symtab-bad-size b/llvm/test/Object/Inputs/macho-invalid-symtab-bad-size new file mode 100644 index 0000000..12b6b89 Binary files /dev/null and b/llvm/test/Object/Inputs/macho-invalid-symtab-bad-size differ diff --git a/llvm/test/Object/Inputs/macho-invalid-symtab-more-than-one b/llvm/test/Object/Inputs/macho-invalid-symtab-more-than-one new file mode 100644 index 0000000..34088bf Binary files /dev/null and b/llvm/test/Object/Inputs/macho-invalid-symtab-more-than-one differ diff --git a/llvm/test/Object/Inputs/macho-invalid-symtab-small b/llvm/test/Object/Inputs/macho-invalid-symtab-small new file mode 100644 index 0000000..cf2294d Binary files /dev/null and b/llvm/test/Object/Inputs/macho-invalid-symtab-small differ diff --git a/llvm/test/Object/Inputs/macho-invalid-symtab-stroff b/llvm/test/Object/Inputs/macho-invalid-symtab-stroff new file mode 100644 index 0000000..44f7761 Binary files /dev/null and b/llvm/test/Object/Inputs/macho-invalid-symtab-stroff differ diff --git a/llvm/test/Object/Inputs/macho-invalid-symtab-stroff-strsize b/llvm/test/Object/Inputs/macho-invalid-symtab-stroff-strsize new file mode 100644 index 0000000..ea57737 Binary files /dev/null and b/llvm/test/Object/Inputs/macho-invalid-symtab-stroff-strsize differ diff --git a/llvm/test/Object/Inputs/macho-invalid-symtab-symoff b/llvm/test/Object/Inputs/macho-invalid-symtab-symoff new file mode 100644 index 0000000..c8251ac Binary files /dev/null and b/llvm/test/Object/Inputs/macho-invalid-symtab-symoff differ diff --git a/llvm/test/Object/Inputs/macho-invalid-symtab-symoff-nsyms b/llvm/test/Object/Inputs/macho-invalid-symtab-symoff-nsyms new file mode 100644 index 0000000..85d79e7 Binary files /dev/null and b/llvm/test/Object/Inputs/macho-invalid-symtab-symoff-nsyms differ diff --git a/llvm/test/Object/macho-invalid.test b/llvm/test/Object/macho-invalid.test index 91e1ea7..c2f6ed2 100644 --- a/llvm/test/Object/macho-invalid.test +++ b/llvm/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)