diff options
-rw-r--r-- | include/llvm/Object/MachO.h | 6 | ||||
-rw-r--r-- | include/llvm/Object/ObjectFile.h | 4 | ||||
-rw-r--r-- | lib/Object/MachOObjectFile.cpp | 35 | ||||
-rw-r--r-- | lib/Object/MachOUniversal.cpp | 10 | ||||
-rw-r--r-- | test/Object/Inputs/macho-invalid-fat_cputype | bin | 0 -> 56 bytes | |||
-rw-r--r-- | test/Object/macho-invalid.test | 3 |
6 files changed, 44 insertions, 14 deletions
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 7906db1e8a7..a26a2ef7dfe 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -194,7 +194,8 @@ public: typedef LoadCommandList::const_iterator load_command_iterator; static Expected<std::unique_ptr<MachOObjectFile>> - create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits); + create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, + uint32_t UniversalCputype = 0, uint32_t UniversalIndex = 0); void moveSymbolNext(DataRefImpl &Symb) const override; @@ -443,7 +444,8 @@ public: private: MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, - Error &Err); + Error &Err, uint32_t UniversalCputype = 0, + uint32_t UniversalIndex = 0); uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 6272a5f056e..07d6b134086 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -300,7 +300,9 @@ public: createELFObjectFile(MemoryBufferRef Object); static Expected<std::unique_ptr<MachOObjectFile>> - createMachOObjectFile(MemoryBufferRef Object); + createMachOObjectFile(MemoryBufferRef Object, + uint32_t UniversalCputype = 0, + uint32_t UniversalIndex = 0); }; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 0edc6a71633..5bfc51ecf62 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -914,18 +914,22 @@ static Error checkTwoLevelHintsCommand(const MachOObjectFile *Obj, Expected<std::unique_ptr<MachOObjectFile>> MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, - bool Is64Bits) { + bool Is64Bits, uint32_t UniversalCputype, + uint32_t UniversalIndex) { Error Err; std::unique_ptr<MachOObjectFile> Obj( new MachOObjectFile(std::move(Object), IsLittleEndian, - Is64Bits, Err)); + Is64Bits, Err, UniversalCputype, + UniversalIndex)); if (Err) return std::move(Err); return std::move(Obj); } MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, - bool Is64bits, Error &Err) + bool Is64bits, Error &Err, + uint32_t UniversalCputype, + uint32_t UniversalIndex) : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr), @@ -933,12 +937,15 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, HasPageZeroSegment(false) { ErrorAsOutParameter ErrAsOutParam(&Err); uint64_t SizeOfHeaders; + uint32_t cputype; if (is64Bit()) { parseHeader(this, Header64, Err); SizeOfHeaders = sizeof(MachO::mach_header_64); + cputype = Header64.cputype; } else { parseHeader(this, Header, Err); SizeOfHeaders = sizeof(MachO::mach_header); + cputype = Header.cputype; } if (Err) return; @@ -947,6 +954,12 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, Err = malformedError("load commands extend past the end of the file"); return; } + if (UniversalCputype != 0 && cputype != UniversalCputype) { + Err = malformedError("universal header architecture: " + + Twine(UniversalIndex) + "'s cputype does not match " + "object file's mach header"); + return; + } uint32_t LoadCommandCount = getHeader().ncmds; LoadCommandInfo Load; @@ -3281,16 +3294,22 @@ bool MachOObjectFile::isRelocatableObject() const { } Expected<std::unique_ptr<MachOObjectFile>> -ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) { +ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer, + uint32_t UniversalCputype, + uint32_t UniversalIndex) { StringRef Magic = Buffer.getBuffer().slice(0, 4); if (Magic == "\xFE\xED\xFA\xCE") - return MachOObjectFile::create(Buffer, false, false); + return MachOObjectFile::create(Buffer, false, false, + UniversalCputype, UniversalIndex); if (Magic == "\xCE\xFA\xED\xFE") - return MachOObjectFile::create(Buffer, true, false); + return MachOObjectFile::create(Buffer, true, false, + UniversalCputype, UniversalIndex); if (Magic == "\xFE\xED\xFA\xCF") - return MachOObjectFile::create(Buffer, false, true); + return MachOObjectFile::create(Buffer, false, true, + UniversalCputype, UniversalIndex); if (Magic == "\xCF\xFA\xED\xFE") - return MachOObjectFile::create(Buffer, true, true); + return MachOObjectFile::create(Buffer, true, true, + UniversalCputype, UniversalIndex); return make_error<GenericBinaryError>("Unrecognized MachO magic number", object_error::invalid_file_type); } diff --git a/lib/Object/MachOUniversal.cpp b/lib/Object/MachOUniversal.cpp index f36e84d93b9..bac9d4dd3e3 100644 --- a/lib/Object/MachOUniversal.cpp +++ b/lib/Object/MachOUniversal.cpp @@ -73,13 +73,17 @@ MachOUniversalBinary::ObjectForArch::getAsObjectFile() const { StringRef ParentData = Parent->getData(); StringRef ObjectData; - if (Parent->getMagic() == MachO::FAT_MAGIC) + uint32_t cputype; + if (Parent->getMagic() == MachO::FAT_MAGIC) { ObjectData = ParentData.substr(Header.offset, Header.size); - else // Parent->getMagic() == MachO::FAT_MAGIC_64 + cputype = Header.cputype; + } else { // Parent->getMagic() == MachO::FAT_MAGIC_64 ObjectData = ParentData.substr(Header64.offset, Header64.size); + cputype = Header64.cputype; + } StringRef ObjectName = Parent->getFileName(); MemoryBufferRef ObjBuffer(ObjectData, ObjectName); - return ObjectFile::createMachOObjectFile(ObjBuffer); + return ObjectFile::createMachOObjectFile(ObjBuffer, cputype, Index); } Expected<std::unique_ptr<Archive>> diff --git a/test/Object/Inputs/macho-invalid-fat_cputype b/test/Object/Inputs/macho-invalid-fat_cputype Binary files differnew file mode 100644 index 00000000000..ce30be86932 --- /dev/null +++ b/test/Object/Inputs/macho-invalid-fat_cputype diff --git a/test/Object/macho-invalid.test b/test/Object/macho-invalid.test index 5a00d0def52..403b968fc05 100644 --- a/test/Object/macho-invalid.test +++ b/test/Object/macho-invalid.test @@ -406,3 +406,6 @@ INVALID-TWOLEVELHINTS-OFFSET: macho-invalid-twolevelhints-offset': truncated or RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-twolevelhints-offset-nhints 2>&1 | FileCheck -check-prefix INVALID-TWOLEVELHINTS-OFFSET-HNINTS %s INVALID-TWOLEVELHINTS-OFFSET-HNINTS: macho-invalid-twolevelhints-offset-nhints': truncated or malformed object (offset field plus nhints times sizeof(struct twolevel_hint) field of LC_TWOLEVEL_HINTS command 0 extends past the end of the file) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-fat_cputype 2>&1 | FileCheck -check-prefix INVALID-FAT-CPUTYPE %s +INVALID-FAT-CPUTYPE: macho-invalid-fat_cputype truncated or malformed object (universal header architecture: 0's cputype does not match object file's mach header) |