diff options
-rw-r--r-- | llvm/lib/Object/MachOObjectFile.cpp | 78 | ||||
-rw-r--r-- | llvm/test/Object/Inputs/macho-invalid-subclient-name_toobig | bin | 0 -> 44 bytes | |||
-rw-r--r-- | llvm/test/Object/Inputs/macho-invalid-subframe-small | bin | 0 -> 44 bytes | |||
-rw-r--r-- | llvm/test/Object/Inputs/macho-invalid-sublibrary-name_offset-toobig | bin | 0 -> 40 bytes | |||
-rw-r--r-- | llvm/test/Object/Inputs/macho-invalid-subumbrella-offset-small | bin | 0 -> 40 bytes | |||
-rw-r--r-- | llvm/test/Object/macho-invalid.test | 12 |
6 files changed, 90 insertions, 0 deletions
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp index 2c93ecbf2b9..9c927adc1f4 100644 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -755,6 +755,33 @@ static Error checkLinkerOptCommand(const MachOObjectFile *Obj, return Error::success(); } +static Error checkSubCommand(const MachOObjectFile *Obj, + const MachOObjectFile::LoadCommandInfo &Load, + uint32_t LoadCommandIndex, const char *CmdName, + size_t SizeOfCmd, const char *CmdStructName, + uint32_t PathOffset, const char *PathFieldName) { + if (PathOffset < SizeOfCmd) + return malformedError("load command " + Twine(LoadCommandIndex) + " " + + CmdName + " " + PathFieldName + ".offset field too " + "small, not past the end of the " + CmdStructName); + if (PathOffset >= Load.C.cmdsize) + return malformedError("load command " + Twine(LoadCommandIndex) + " " + + CmdName + " " + PathFieldName + ".offset field " + "extends past the end of the load command"); + // Make sure there is a null between the starting offset of the path and + // the end of the load command. + uint32_t i; + const char *P = (const char *)Load.Ptr; + for (i = PathOffset; i < Load.C.cmdsize; i++) + if (P[i] == '\0') + break; + if (i >= Load.C.cmdsize) + return malformedError("load command " + Twine(LoadCommandIndex) + " " + + CmdName + " " + PathFieldName + " name extends past " + "the end of the load command"); + return Error::success(); +} + Expected<std::unique_ptr<MachOObjectFile>> MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits) { @@ -986,6 +1013,57 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) { if ((Err = checkLinkerOptCommand(this, Load, I))) return; + } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) { + if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) { + Err = malformedError("load command " + Twine(I) + + " LC_SUB_FRAMEWORK cmdsize too small"); + return; + } + MachO::sub_framework_command S = + getStruct<MachO::sub_framework_command>(this, Load.Ptr); + if ((Err = checkSubCommand(this, Load, I, "LC_SUB_FRAMEWORK", + sizeof(MachO::sub_framework_command), + "sub_framework_command", S.umbrella, + "umbrella"))) + return; + } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) { + if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) { + Err = malformedError("load command " + Twine(I) + + " LC_SUB_UMBRELLA cmdsize too small"); + return; + } + MachO::sub_umbrella_command S = + getStruct<MachO::sub_umbrella_command>(this, Load.Ptr); + if ((Err = checkSubCommand(this, Load, I, "LC_SUB_UMBRELLA", + sizeof(MachO::sub_umbrella_command), + "sub_umbrella_command", S.sub_umbrella, + "sub_umbrella"))) + return; + } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) { + if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) { + Err = malformedError("load command " + Twine(I) + + " LC_SUB_LIBRARY cmdsize too small"); + return; + } + MachO::sub_library_command S = + getStruct<MachO::sub_library_command>(this, Load.Ptr); + if ((Err = checkSubCommand(this, Load, I, "LC_SUB_LIBRARY", + sizeof(MachO::sub_library_command), + "sub_library_command", S.sub_library, + "sub_library"))) + return; + } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) { + if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) { + Err = malformedError("load command " + Twine(I) + + " LC_SUB_CLIENT cmdsize too small"); + return; + } + MachO::sub_client_command S = + getStruct<MachO::sub_client_command>(this, Load.Ptr); + if ((Err = checkSubCommand(this, Load, I, "LC_SUB_CLIENT", + sizeof(MachO::sub_client_command), + "sub_client_command", S.client, "client"))) + return; } if (I < LoadCommandCount - 1) { if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load)) diff --git a/llvm/test/Object/Inputs/macho-invalid-subclient-name_toobig b/llvm/test/Object/Inputs/macho-invalid-subclient-name_toobig Binary files differnew file mode 100644 index 00000000000..d0a8ee9eb82 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-subclient-name_toobig diff --git a/llvm/test/Object/Inputs/macho-invalid-subframe-small b/llvm/test/Object/Inputs/macho-invalid-subframe-small Binary files differnew file mode 100644 index 00000000000..73497f16034 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-subframe-small diff --git a/llvm/test/Object/Inputs/macho-invalid-sublibrary-name_offset-toobig b/llvm/test/Object/Inputs/macho-invalid-sublibrary-name_offset-toobig Binary files differnew file mode 100644 index 00000000000..95522e60e50 --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-sublibrary-name_offset-toobig diff --git a/llvm/test/Object/Inputs/macho-invalid-subumbrella-offset-small b/llvm/test/Object/Inputs/macho-invalid-subumbrella-offset-small Binary files differnew file mode 100644 index 00000000000..ac022c77cdd --- /dev/null +++ b/llvm/test/Object/Inputs/macho-invalid-subumbrella-offset-small diff --git a/llvm/test/Object/macho-invalid.test b/llvm/test/Object/macho-invalid.test index 31948d8505e..d9af43933ab 100644 --- a/llvm/test/Object/macho-invalid.test +++ b/llvm/test/Object/macho-invalid.test @@ -355,3 +355,15 @@ INVALID-LINKOPT-BAD-SIZE: macho-invalid-linkopt-bad-size': truncated or malforme RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-linkopt-bad-count 2>&1 | FileCheck -check-prefix INVALID-LINKOPT-BAD-COUNT %s INVALID-LINKOPT-BAD-COUNT: macho-invalid-linkopt-bad-count': truncated or malformed object (load command 0 LC_LINKER_OPTION string count 3 does not match number of strings) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-subframe-small 2>&1 | FileCheck -check-prefix INVALID-SUBFRAME-SMALL %s +INVALID-SUBFRAME-SMALL: macho-invalid-subframe-small': truncated or malformed object (load command 0 LC_SUB_FRAMEWORK cmdsize too small) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-subumbrella-offset-small 2>&1 | FileCheck -check-prefix INVALID-SUBUMBRELLA-OFFSET-SMALL %s +INVALID-SUBUMBRELLA-OFFSET-SMALL: macho-invalid-subumbrella-offset-small': truncated or malformed object (load command 0 LC_SUB_UMBRELLA sub_umbrella.offset field too small, not past the end of the sub_umbrella_command) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-sublibrary-name_offset-toobig 2>&1 | FileCheck -check-prefix INVALID-SUBLIB-NAME_OFFSET-TOOBIG %s +INVALID-SUBLIB-NAME_OFFSET-TOOBIG: macho-invalid-sublibrary-name_offset-toobig': truncated or malformed object (load command 0 LC_SUB_LIBRARY sub_library.offset field extends past the end of the load command) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-subclient-name_toobig 2>&1 | FileCheck -check-prefix INVALID-SUBCLIENT-NAME-TOOBIG %s +INVALID-SUBCLIENT-NAME-TOOBIG: macho-invalid-subclient-name_toobig': truncated or malformed object (load command 0 LC_SUB_CLIENT client name extends past the end of the load command) |