From f77b75655a294954e2a7912975091138b7be193a Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Tue, 30 Aug 2016 21:28:30 +0000 Subject: [PATCH] =?UTF-8?q?Next=20set=20of=20additional=20error=20checks?= =?UTF-8?q?=20for=20invalid=20Mach-O=20files=20for=20bad=20LC=5FDYSYMTAB?= =?UTF-8?q?=E2=80=99s.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This contains the missing checks for LC_DYSYMTAB load command fields. llvm-svn: 280161 --- lib/Object/MachOObjectFile.cpp | 105 +++++++++++++++++- .../Inputs/macho-invalid-dysymtab-bad-size | Bin 0 -> 112 bytes .../macho-invalid-dysymtab-extrefsymoff | Bin 0 -> 108 bytes ...-invalid-dysymtab-extrefsymoff-nextrefsyms | Bin 0 -> 108 bytes .../Inputs/macho-invalid-dysymtab-extreloff | Bin 0 -> 108 bytes .../macho-invalid-dysymtab-indirectsymoff | Bin 0 -> 108 bytes ...alid-dysymtab-indirectsymoff-nindirectsyms | Bin 0 -> 108 bytes .../Inputs/macho-invalid-dysymtab-locreloff | Bin 0 -> 108 bytes .../macho-invalid-dysymtab-locreloff-nlocrel | Bin 0 -> 108 bytes .../Inputs/macho-invalid-dysymtab-modtaboff | Bin 0 -> 108 bytes .../macho-invalid-dysymtab-modtaboff-nmodtab | Bin 0 -> 108 bytes .../macho-invalid-dysymtab-more-than-one | Bin 0 -> 188 bytes .../Inputs/macho-invalid-dysymtab-small | Bin 0 -> 108 bytes .../Inputs/macho-invalid-dysymtab-tocoff | Bin 0 -> 108 bytes .../Inputs/macho-invalid-dysymtab-tocoff-ntoc | Bin 0 -> 108 bytes test/Object/macho-invalid.test | 45 ++++++++ 16 files changed, 144 insertions(+), 6 deletions(-) create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-bad-size create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-extrefsymoff create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-extrefsymoff-nextrefsyms create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-extreloff create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-indirectsymoff create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-indirectsymoff-nindirectsyms create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-locreloff create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-locreloff-nlocrel create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-modtaboff create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-modtaboff-nmodtab create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-more-than-one create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-small create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-tocoff create mode 100644 test/Object/Inputs/macho-invalid-dysymtab-tocoff-ntoc diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 26fd9a68724..b5ca95add73 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -372,11 +372,108 @@ static Error checkSymtabCommand(const MachOObjectFile *Obj, 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(); } +static Error checkDysymtabCommand(const MachOObjectFile *Obj, + const MachOObjectFile::LoadCommandInfo &Load, + uint32_t LoadCommandIndex, + const char **DysymtabLoadCmd) { + if (Load.C.cmdsize < sizeof(MachO::dysymtab_command)) + return malformedError("load command " + Twine(LoadCommandIndex) + + " LC_DYSYMTAB cmdsize too small"); + if (*DysymtabLoadCmd != nullptr) + return malformedError("more than one LC_DYSYMTAB command"); + MachO::dysymtab_command Dysymtab = + getStruct(Obj, Load.Ptr); + if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command)) + return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) + + " has incorrect cmdsize"); + uint64_t FileSize = Obj->getData().size(); + if (Dysymtab.tocoff > FileSize) + return malformedError("tocoff field of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + uint64_t BigSize = Dysymtab.ntoc; + BigSize *= sizeof(MachO::dylib_table_of_contents); + BigSize += Dysymtab.tocoff; + if (BigSize > FileSize) + return malformedError("tocoff field plus ntoc field times sizeof(struct " + "dylib_table_of_contents) of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + if (Dysymtab.modtaboff > FileSize) + return malformedError("modtaboff field of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + BigSize = Dysymtab.nmodtab; + const char *struct_dylib_module_name; + if (Obj->is64Bit()) { + BigSize *= sizeof(MachO::dylib_module_64); + struct_dylib_module_name = "struct dylib_module_64"; + } else { + BigSize *= sizeof(MachO::dylib_module); + struct_dylib_module_name = "struct dylib_module"; + } + BigSize += Dysymtab.modtaboff; + if (BigSize > FileSize) + return malformedError("modtaboff field plus nmodtab field times sizeof(" + + Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB " + "command " + Twine(LoadCommandIndex) + " extends " + "past the end of the file"); + if (Dysymtab.extrefsymoff > FileSize) + return malformedError("extrefsymoff field of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + BigSize = Dysymtab.nextrefsyms; + BigSize *= sizeof(MachO::dylib_reference); + BigSize += Dysymtab.extrefsymoff; + if (BigSize > FileSize) + return malformedError("extrefsymoff field plus nextrefsyms field times " + "sizeof(struct dylib_reference) of LC_DYSYMTAB " + "command " + Twine(LoadCommandIndex) + " extends " + "past the end of the file"); + if (Dysymtab.indirectsymoff > FileSize) + return malformedError("indirectsymoff field of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + BigSize = Dysymtab.nindirectsyms; + BigSize *= sizeof(uint32_t); + BigSize += Dysymtab.indirectsymoff; + if (BigSize > FileSize) + return malformedError("indirectsymoff field plus nindirectsyms field times " + "sizeof(uint32_t) of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + if (Dysymtab.extreloff > FileSize) + return malformedError("extreloff field of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + BigSize = Dysymtab.nextrel; + BigSize *= sizeof(MachO::relocation_info); + BigSize += Dysymtab.extreloff; + if (BigSize > FileSize) + return malformedError("extreloff field plus nextrel field times sizeof" + "(struct relocation_info) of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + if (Dysymtab.locreloff > FileSize) + return malformedError("locreloff field of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + BigSize = Dysymtab.nlocrel; + BigSize *= sizeof(MachO::relocation_info); + BigSize += Dysymtab.locreloff; + if (BigSize > FileSize) + return malformedError("locreloff field plus nlocrel field times sizeof" + "(struct relocation_info) of LC_DYSYMTAB command " + + Twine(LoadCommandIndex) + " extends past the end of " + "the file"); + *DysymtabLoadCmd = Load.Ptr; + return Error::success(); +} + Expected> MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits) { @@ -450,12 +547,8 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd))) return; } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { - // Multiple dynamic symbol tables - if (DysymtabLoadCmd) { - Err = malformedError("Multiple dynamic symbol tables"); + if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd))) return; - } - DysymtabLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { // Multiple data in code tables if (DataInCodeLoadCmd) { diff --git a/test/Object/Inputs/macho-invalid-dysymtab-bad-size b/test/Object/Inputs/macho-invalid-dysymtab-bad-size new file mode 100644 index 0000000000000000000000000000000000000000..49065d6334f72c2703bc63dc5d91ca4998b7aba9 GIT binary patch literal 112 hcmX^2>+L^w1_lOZAZCQ(5FiZ#+&~Otg9WHS007zj1aklY literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-dysymtab-extrefsymoff b/test/Object/Inputs/macho-invalid-dysymtab-extrefsymoff new file mode 100644 index 0000000000000000000000000000000000000000..0e80fba0f23afc2c9830151011cea0cdb4d39040 GIT binary patch literal 108 lcmX^2>+L^w1_lOZAZCQ(03Zzl+&~Otg9Qi>CLjaw007KD1fT!_ literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-dysymtab-extrefsymoff-nextrefsyms b/test/Object/Inputs/macho-invalid-dysymtab-extrefsymoff-nextrefsyms new file mode 100644 index 0000000000000000000000000000000000000000..f08b1330241d6d46fcb352b001febb888da3d66c GIT binary patch literal 108 mcmX^2>+L^w1_lOZAZCQ(03Zzl+&~Otg9Qi>IY9XcJZb>k!38e> literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-dysymtab-extreloff b/test/Object/Inputs/macho-invalid-dysymtab-extreloff new file mode 100644 index 0000000000000000000000000000000000000000..d04eccaed8f24c23c17fce878407a85be6d7fce3 GIT binary patch literal 108 lcmX^2>+L^w1_lOZAZCQ(03Zzl+&~Otg9S(=)`1K}0szpE1sVVV literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-dysymtab-indirectsymoff b/test/Object/Inputs/macho-invalid-dysymtab-indirectsymoff new file mode 100644 index 0000000000000000000000000000000000000000..46d94780b448bd073423586b81db7628e9d711a5 GIT binary patch literal 108 lcmX^2>+L^w1_lOZAZCQ(03Zzl+&~Otg9V5rGC&4l0RYc<1k?Zk literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-dysymtab-indirectsymoff-nindirectsyms b/test/Object/Inputs/macho-invalid-dysymtab-indirectsymoff-nindirectsyms new file mode 100644 index 0000000000000000000000000000000000000000..9c4b3b3781cc1d4f95d52c52b18b6836a5e73765 GIT binary patch literal 108 ocmX^2>+L^w1_lOZAZCQ(03Zzl+&~Otg9V5ra)9a-K!%|K0Mb+h_y7O^ literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-dysymtab-locreloff b/test/Object/Inputs/macho-invalid-dysymtab-locreloff new file mode 100644 index 0000000000000000000000000000000000000000..0ddab0c3b876fc7fe17aa2c1b770d62c7e75b5b8 GIT binary patch literal 108 lcmX^2>+L^w1_lOZAZCQ(03Zzl+&~Otg9XSWPJj#s0szbC1vCHv literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-dysymtab-locreloff-nlocrel b/test/Object/Inputs/macho-invalid-dysymtab-locreloff-nlocrel new file mode 100644 index 0000000000000000000000000000000000000000..94f4b2d3f86a608fa6218124d3430f3855f50b92 GIT binary patch literal 108 ncmX^2>+L^w1_lOZAZCQ(03Zzl+&~Otg9XSWa)A0?01XEK%%lat literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-dysymtab-modtaboff b/test/Object/Inputs/macho-invalid-dysymtab-modtaboff new file mode 100644 index 0000000000000000000000000000000000000000..c8e80ac2105de90011207583c994dc67c250f699 GIT binary patch literal 108 lcmX^2>+L^w1_lOZAZCQ(03Zzl+&~Otg9UI9WjMsqg#p+R1mOSx literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-dysymtab-modtaboff-nmodtab b/test/Object/Inputs/macho-invalid-dysymtab-modtaboff-nmodtab new file mode 100644 index 0000000000000000000000000000000000000000..dd643ca0698d5fc61b77840be584df729254c35b GIT binary patch literal 108 ocmX^2>+L^w1_lOZAZCQ(03Zzl+&~Otg9UI9IY4n99CFCQ0N61E;{X5v literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-dysymtab-more-than-one b/test/Object/Inputs/macho-invalid-dysymtab-more-than-one new file mode 100644 index 0000000000000000000000000000000000000000..0a0f8593d228d2048c8102bac81f7c2c8f880042 GIT binary patch literal 188 lcmX^2>+L^w1_lOZAZ7$&CLmq_#2~;8!~tLybqH#k2LN}A1s4DS literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-dysymtab-small b/test/Object/Inputs/macho-invalid-dysymtab-small new file mode 100644 index 0000000000000000000000000000000000000000..53c61f9cc7915d2da47c6ec284f1c1aefd95d1f5 GIT binary patch literal 108 gcmX^2>+L^w1_lOZAZCPOA0Q0^+&~Otg9Rug0K*XkV*mgE literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-dysymtab-tocoff b/test/Object/Inputs/macho-invalid-dysymtab-tocoff new file mode 100644 index 0000000000000000000000000000000000000000..9a86fd84c2184c64b4863999d78c2ddd5012cd05 GIT binary patch literal 108 lcmX^2>+L^w1_lOZAZCQ(03Zzl+&~Otg9Xrt5;Q&`E&$tM1m6Gv literal 0 HcmV?d00001 diff --git a/test/Object/Inputs/macho-invalid-dysymtab-tocoff-ntoc b/test/Object/Inputs/macho-invalid-dysymtab-tocoff-ntoc new file mode 100644 index 0000000000000000000000000000000000000000..ec09e3128630993b46e9d5212cd6e82e72236b29 GIT binary patch literal 108 ocmX^2>+L^w1_lOZAZCQ(03Zzl+&~Otg9Xrt93Y&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) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-small 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-SMALL %s +INVALID-DYSYMTAB-SMALL: macho-invalid-dysymtab-small': truncated or malformed object (load command 0 LC_DYSYMTAB cmdsize too small) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-more-than-one 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-MORE-THAN-ONE %s +INVALID-DYSYMTAB-MORE-THAN-ONE: macho-invalid-dysymtab-more-than-one': truncated or malformed object (more than one LC_DYSYMTAB command) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-bad-size 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-BAD-SIZE %s +INVALID-DYSYMTAB-BAD-SIZE: macho-invalid-dysymtab-bad-size': truncated or malformed object (LC_DYSYMTAB command 0 has incorrect cmdsize) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-tocoff 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF %s +INVALID-DYSYMTAB-TOCOFF: macho-invalid-dysymtab-tocoff': truncated or malformed object (tocoff field of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-tocoff-ntoc 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-NTOC %s +INVALID-DYSYMTAB-TOCOFF-NTOC: macho-invalid-dysymtab-tocoff-ntoc': truncated or malformed object (tocoff field plus ntoc field times sizeof(struct dylib_table_of_contents) of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-modtaboff 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-MODTABOFF %s +INVALID-DYSYMTAB-TOCOFF-MODTABOFF: macho-invalid-dysymtab-modtaboff': truncated or malformed object (modtaboff field of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-modtaboff-nmodtab 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-MODTABOFF-NMODTAB %s +INVALID-DYSYMTAB-TOCOFF-MODTABOFF-NMODTAB: macho-invalid-dysymtab-modtaboff-nmodtab': truncated or malformed object (modtaboff field plus nmodtab field times sizeof(struct dylib_module) of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-extrefsymoff 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-EXTREFSYMOFF %s +INVALID-DYSYMTAB-TOCOFF-EXTREFSYMOFF: macho-invalid-dysymtab-extrefsymoff': truncated or malformed object (extrefsymoff field of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-extrefsymoff-nextrefsyms 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-EXTREFSYMOFF-NEXTREFSYMS %s +INVALID-DYSYMTAB-TOCOFF-EXTREFSYMOFF-NEXTREFSYMS: macho-invalid-dysymtab-extrefsymoff-nextrefsyms': truncated or malformed object (extrefsymoff field plus nextrefsyms field times sizeof(struct dylib_reference) of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-indirectsymoff 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-INDIRECTSYMOFF %s +INVALID-DYSYMTAB-TOCOFF-INDIRECTSYMOFF: macho-invalid-dysymtab-indirectsymoff': truncated or malformed object (indirectsymoff field of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-indirectsymoff-nindirectsyms 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-INDIRECTSYMOFF-NINDIRECTSYMS %s +INVALID-DYSYMTAB-TOCOFF-INDIRECTSYMOFF-NINDIRECTSYMS: macho-invalid-dysymtab-indirectsymoff-nindirectsyms': truncated or malformed object (indirectsymoff field plus nindirectsyms field times sizeof(uint32_t) of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-extreloff 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-EXTRELOFF %s +INVALID-DYSYMTAB-TOCOFF-EXTRELOFF: macho-invalid-dysymtab-extreloff': truncated or malformed object (extreloff field of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-extreloff-nextrel 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-EXTRELOFF-NEXTREL %s +INVALID-DYSYMTAB-TOCOFF-EXTRELOFF-NEXTREL: macho-invalid-dysymtab-extreloff-nextrel': truncated or malformed object (extreloff field plus nextrel field times sizeof(struct relocation_info) of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-locreloff 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-LOCRELOFF %s +INVALID-DYSYMTAB-TOCOFF-LOCRELOFF: macho-invalid-dysymtab-locreloff': truncated or malformed object (locreloff field of LC_DYSYMTAB command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-locreloff-nlocrel 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-LOCRELOFF-NLOCREL %s +INVALID-DYSYMTAB-TOCOFF-LOCRELOFF-NLOCREL: macho-invalid-dysymtab-locreloff-nlocrel': truncated or malformed object (locreloff field plus nlocrel field times sizeof(struct relocation_info) of LC_DYSYMTAB command 0 extends past the end of the file)