diff --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h index 32c72a0cc3d3..356393cce2d7 100644 --- a/llvm/include/llvm/Object/Archive.h +++ b/llvm/include/llvm/Object/Archive.h @@ -65,7 +65,10 @@ public: bool isThinMember() const; public: - Child(const Archive *Parent, const char *Start); + Child(const Archive *Parent, const char *Start, + std::error_code *EC); + static ErrorOr> create(const Archive *Parent, + const char *Start); bool operator ==(const Child &other) const { assert(Parent == other.Parent); @@ -77,7 +80,7 @@ public: } const Archive *getParent() const { return Parent; } - Child getNext() const; + ErrorOr getNext() const; ErrorOr getName() const; StringRef getRawName() const { return getHeader()->getName(); } @@ -93,9 +96,9 @@ public: return getHeader()->getAccessMode(); } /// \return the size of the archive member without the header or padding. - uint64_t getSize() const; + ErrorOr getSize() const; /// \return the size in the archive header for this member. - uint64_t getRawSize() const; + ErrorOr getRawSize() const; ErrorOr getBuffer() const; uint64_t getChildOffset() const; @@ -107,28 +110,35 @@ public: }; class child_iterator { - Child child; + ErrorOr child; public: - child_iterator() : child(Child(nullptr, nullptr)) {} + child_iterator() : child(Child(nullptr, nullptr, nullptr)) {} child_iterator(const Child &c) : child(c) {} - const Child *operator->() const { return &child; } - const Child &operator*() const { return child; } + child_iterator(std::error_code EC) : child(EC) {} + const ErrorOr *operator->() const { return &child; } + const ErrorOr &operator*() const { return child; } bool operator==(const child_iterator &other) const { - return child == other.child; + if ((*this)->getError()) + return false; + if (other->getError()) + return false; + return (*this)->get() == other->get(); } bool operator!=(const child_iterator &other) const { return !(*this == other); } - bool operator<(const child_iterator &other) const { - return child < other.child; - } + // No operator< as we can't do less than compares with iterators that + // contain errors. + // Code in loops with child_iterators must check for errors on each loop + // iteration. And if there is an error break out of the loop. child_iterator &operator++() { // Preincrement - child = child.getNext(); + assert(child && "Can't increment iterator with error"); + child = child->getNext(); return *this; } }; @@ -212,7 +222,7 @@ public: StringRef getSymbolTable() const { // We know that the symbol table is not an external file, // so we just assert there is no error. - return *SymbolTable->getBuffer(); + return *(*SymbolTable)->getBuffer(); } uint32_t getNumberOfSymbols() const; diff --git a/llvm/include/llvm/Support/ErrorOr.h b/llvm/include/llvm/Support/ErrorOr.h index 46b619217753..5021468b4da9 100644 --- a/llvm/include/llvm/Support/ErrorOr.h +++ b/llvm/include/llvm/Support/ErrorOr.h @@ -91,6 +91,7 @@ private: typedef typename std::remove_reference::type &reference; typedef const typename std::remove_reference::type &const_reference; typedef typename std::remove_reference::type *pointer; + typedef const typename std::remove_reference::type *const_pointer; public: template @@ -183,10 +184,18 @@ public: return toPointer(getStorage()); } + const_pointer operator ->() const { + return toPointer(getStorage()); + } + reference operator *() { return *getStorage(); } + const_reference operator *() const { + return *getStorage(); + } + private: template void copyConstruct(const ErrorOr &Other) { @@ -246,10 +255,19 @@ private: return Val; } + const_pointer toPointer(const_pointer Val) const { + return Val; + } + pointer toPointer(wrap *Val) { return &Val->get(); } + const_pointer toPointer(const wrap *Val) const { + return &Val->get(); + } + + storage_type *getStorage() { assert(!HasError && "Cannot get value when an error exists!"); return reinterpret_cast(TStorage.buffer); diff --git a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp index bbe4432d36b3..a7238e4ebc33 100644 --- a/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -318,10 +318,10 @@ RuntimeDyld::SymbolInfo MCJIT::findSymbol(const std::string &Name, object::Archive *A = OB.getBinary(); // Look for our symbols in each Archive object::Archive::child_iterator ChildIt = A->findSym(Name); - if (ChildIt != A->child_end()) { + if (*ChildIt && ChildIt != A->child_end()) { // FIXME: Support nested archives? ErrorOr> ChildBinOrErr = - ChildIt->getAsBinary(); + (*ChildIt)->getAsBinary(); if (ChildBinOrErr.getError()) continue; std::unique_ptr &ChildBin = ChildBinOrErr.get(); diff --git a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index 951993f75e4c..e52df2db79f2 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -253,10 +253,10 @@ private: object::Archive *A = OB.getBinary(); // Look for our symbols in each Archive object::Archive::child_iterator ChildIt = A->findSym(Name); - if (ChildIt != A->child_end()) { + if (*ChildIt && ChildIt != A->child_end()) { // FIXME: Support nested archives? ErrorOr> ChildBinOrErr = - ChildIt->getAsBinary(); + (*ChildIt)->getAsBinary(); if (ChildBinOrErr.getError()) continue; std::unique_ptr &ChildBin = ChildBinOrErr.get(); diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp index 667732baa279..1cc3c48c6c3c 100644 --- a/llvm/lib/Object/Archive.cpp +++ b/llvm/lib/Object/Archive.cpp @@ -46,7 +46,7 @@ StringRef ArchiveMemberHeader::getName() const { ErrorOr ArchiveMemberHeader::getSize() const { uint32_t Ret; if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, Ret)) - return object_error::parse_failed; + return object_error::parse_failed; // Size is not a decimal number. return Ret; } @@ -82,7 +82,8 @@ unsigned ArchiveMemberHeader::getGID() const { return Ret; } -Archive::Child::Child(const Archive *Parent, const char *Start) +Archive::Child::Child(const Archive *Parent, const char *Start, + std::error_code *EC) : Parent(Parent) { if (!Start) return; @@ -90,7 +91,13 @@ Archive::Child::Child(const Archive *Parent, const char *Start) uint64_t Size = sizeof(ArchiveMemberHeader); Data = StringRef(Start, Size); if (!isThinMember()) { - Size += getRawSize(); + ErrorOr MemberSize = getRawSize(); + if (MemberSize.getError()) { + assert (EC && "Error must be caught"); + *EC = MemberSize.getError(); + return; + } + Size += MemberSize.get(); Data = StringRef(Start, Size); } @@ -100,26 +107,38 @@ Archive::Child::Child(const Archive *Parent, const char *Start) StringRef Name = getRawName(); if (Name.startswith("#1/")) { uint64_t NameSize; - if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize)) - llvm_unreachable("Long name length is not an integer"); + if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize)) { + if (EC) + *EC = object_error::parse_failed; // Long name offset is not an integer. + return; + } StartOfFile += NameSize; } } -uint64_t Archive::Child::getSize() const { +ErrorOr> Archive::Child::create( + const Archive *Parent, const char *Start) { + std::error_code EC; + std::unique_ptr Ret(new Archive::Child(Parent, Start, &EC)); + if (EC) + return EC; + return std::move(Ret); +} + +ErrorOr Archive::Child::getSize() const { if (Parent->IsThin) { ErrorOr Size = getHeader()->getSize(); - if (Size.getError()) - return 0; + if (std::error_code EC = Size.getError()) + return EC; return Size.get(); } return Data.size() - StartOfFile; } -uint64_t Archive::Child::getRawSize() const { +ErrorOr Archive::Child::getRawSize() const { ErrorOr Size = getHeader()->getSize(); - if (Size.getError()) - return 0; + if (std::error_code EC = Size.getError()) + return EC; return Size.get(); } @@ -129,8 +148,12 @@ bool Archive::Child::isThinMember() const { } ErrorOr Archive::Child::getBuffer() const { - if (!isThinMember()) - return StringRef(Data.data() + StartOfFile, getSize()); + if (!isThinMember()) { + ErrorOr Size = getSize(); + if (std::error_code EC = Size.getError()) + return EC; + return StringRef(Data.data() + StartOfFile, Size.get()); + } ErrorOr Name = getName(); if (std::error_code EC = Name.getError()) return EC; @@ -144,19 +167,28 @@ ErrorOr Archive::Child::getBuffer() const { return Parent->ThinBuffers.back()->getBuffer(); } -Archive::Child Archive::Child::getNext() const { +ErrorOr Archive::Child::getNext() const { size_t SpaceToSkip = Data.size(); // If it's odd, add 1 to make it even. + size_t Pad = 0; if (SpaceToSkip & 1) - ++SpaceToSkip; + Pad++; - const char *NextLoc = Data.data() + SpaceToSkip; + const char *NextLoc = Data.data() + SpaceToSkip + Pad; + + // Check to see if this is at the end of the archive. + if (NextLoc == Parent->Data.getBufferEnd() || + NextLoc == Parent->Data.getBufferEnd() - Pad ) + return Child(Parent, nullptr, nullptr); // Check to see if this is past the end of the archive. - if (NextLoc >= Parent->Data.getBufferEnd()) - return Child(Parent, nullptr); + if (NextLoc > Parent->Data.getBufferEnd()) + return object_error::parse_failed; - return Child(Parent, NextLoc); + auto ChildOrErr = Child::create(Parent, NextLoc); + if (std::error_code EC = ChildOrErr.getError()) + return EC; + return std::move(*ChildOrErr.get()); } uint64_t Archive::Child::getChildOffset() const { @@ -178,17 +210,23 @@ ErrorOr Archive::Child::getName() const { // Get the offset. std::size_t offset; if (name.substr(1).rtrim(" ").getAsInteger(10, offset)) - llvm_unreachable("Long name offset is not an integer"); - const char *addr = Parent->StringTable->Data.begin() + return object_error::parse_failed; // Long name offset is not an integer. + // Check for bad stringtable iterator. + if (std::error_code EC = Parent->StringTable->getError()) + return EC; + const char *addr = (*Parent->StringTable)->Data.begin() + sizeof(ArchiveMemberHeader) + offset; // Verify it. + auto Size = (*Parent->StringTable)->getSize(); + if (std::error_code EC = Size.getError()) + return EC; if (Parent->StringTable == Parent->child_end() - || addr < (Parent->StringTable->Data.begin() + || addr < ((*Parent->StringTable)->Data.begin() + sizeof(ArchiveMemberHeader)) - || addr > (Parent->StringTable->Data.begin() + || addr > ((*Parent->StringTable)->Data.begin() + sizeof(ArchiveMemberHeader) - + Parent->StringTable->getSize())) + + Size.get())) return object_error::parse_failed; // GNU long file names end with a "/\n". @@ -200,7 +238,7 @@ ErrorOr Archive::Child::getName() const { } else if (name.startswith("#1/")) { uint64_t name_size; if (name.substr(3).rtrim(" ").getAsInteger(10, name_size)) - llvm_unreachable("Long name length is not an ingeter"); + return object_error::parse_failed; // Long name offset is not an integer. return Data.substr(sizeof(ArchiveMemberHeader), name_size) .rtrim(StringRef("\0", 1)); } @@ -256,12 +294,12 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) child_iterator i = child_begin(false); child_iterator e = child_end(); - if (i == e) { - ec = std::error_code(); + if (!*i || i == e) { + ec = i->getError(); return; } - StringRef Name = i->getRawName(); + StringRef Name = (*i)->getRawName(); // Below is the pattern that is used to figure out the archive format // GNU archive format @@ -286,6 +324,11 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) Format = K_BSD; SymbolTable = i; ++i; + if (!*i) { + ec = i->getError(); + return; + } + FirstRegular = i; ec = std::error_code(); return; @@ -294,7 +337,7 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) if (Name.startswith("#1/")) { Format = K_BSD; // We know this is BSD, so getName will work since there is no string table. - ErrorOr NameOrErr = i->getName(); + ErrorOr NameOrErr = (*i)->getName(); ec = NameOrErr.getError(); if (ec) return; @@ -302,6 +345,10 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") { SymbolTable = i; ++i; + if (!*i) { + ec = i->getError(); + return; + } } FirstRegular = i; return; @@ -319,17 +366,21 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) has64SymTable = true; ++i; - if (i == e) { - ec = std::error_code(); + if (!*i || i == e) { + ec = i->getError(); return; } - Name = i->getRawName(); + Name = (*i)->getRawName(); } if (Name == "//") { Format = has64SymTable ? K_MIPS64 : K_GNU; StringTable = i; ++i; + if (!*i) { + ec = i->getError(); + return; + } FirstRegular = i; ec = std::error_code(); return; @@ -351,17 +402,25 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) SymbolTable = i; ++i; + if (!*i) { + ec = i->getError(); + return; + } if (i == e) { FirstRegular = i; ec = std::error_code(); return; } - Name = i->getRawName(); + Name = (*i)->getRawName(); if (Name == "//") { StringTable = i; ++i; + if (!*i) { + ec = i->getError(); + return; + } } FirstRegular = i; @@ -376,12 +435,20 @@ Archive::child_iterator Archive::child_begin(bool SkipInternal) const { return FirstRegular; const char *Loc = Data.getBufferStart() + strlen(Magic); - Child c(this, Loc); - return c; + auto ChildOrErr = Child::create(this, Loc); + if (std::error_code EC = ChildOrErr.getError()) + return child_iterator(EC); + Child c = *(ChildOrErr.get()); + return child_iterator(c); } Archive::child_iterator Archive::child_end() const { - return Child(this, nullptr); + // This with a second argument of nullptr can't return an Error. + auto ChildOrErr = Child::create(this, nullptr); + if (ChildOrErr.getError()) + llvm_unreachable("Can't create Archive::child_end()."); + Child c = *(ChildOrErr.get()); + return child_iterator(c); } StringRef Archive::Symbol::getName() const { @@ -433,7 +500,10 @@ ErrorOr Archive::Symbol::getMember() const { } const char *Loc = Parent->getData().begin() + Offset; - child_iterator Iter(Child(Parent, Loc)); + auto ChildOrErr = Child::create(Parent, Loc); + if (std::error_code EC = ChildOrErr.getError()) + return EC; + child_iterator Iter(std::move(*ChildOrErr.get())); return Iter; } diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp index dae0188a21e1..1f304ccfb75a 100644 --- a/llvm/lib/Object/ArchiveWriter.cpp +++ b/llvm/lib/Object/ArchiveWriter.cpp @@ -347,10 +347,10 @@ llvm::writeArchive(StringRef ArcName, MemberRef = Buffers.back()->getMemBufferRef(); } else { object::Archive::child_iterator OldMember = Member.getOld(); - assert((!Thin || OldMember->getParent()->isThin()) && + assert((!Thin || (*OldMember && (*OldMember)->getParent()->isThin())) && "Thin archives cannot refers to member of other archives"); ErrorOr MemberBufferOrErr = - OldMember->getMemoryBufferRef(); + (*OldMember)->getMemoryBufferRef(); if (auto EC = MemberBufferOrErr.getError()) return std::make_pair("", EC); MemberRef = MemberBufferOrErr.get(); @@ -398,10 +398,10 @@ llvm::writeArchive(StringRef ArcName, Perms = Status.permissions(); } else { object::Archive::child_iterator OldMember = I.getOld(); - ModTime = OldMember->getLastModified(); - UID = OldMember->getUID(); - GID = OldMember->getGID(); - Perms = OldMember->getAccessMode(); + ModTime = (*OldMember)->getLastModified(); + UID = (*OldMember)->getUID(); + GID = (*OldMember)->getGID(); + Perms = (*OldMember)->getAccessMode(); } if (I.isNewMember()) { @@ -412,8 +412,11 @@ llvm::writeArchive(StringRef ArcName, Status.getSize()); } else { object::Archive::child_iterator OldMember = I.getOld(); + ErrorOr Size = (*OldMember)->getSize(); + if (std::error_code EC = Size.getError()) + return std::make_pair("", EC); printMemberHeader(Out, Kind, Thin, I.getName(), StringMapIndexIter, - ModTime, UID, GID, Perms, OldMember->getSize()); + ModTime, UID, GID, Perms, Size.get()); } if (!Thin) diff --git a/llvm/test/tools/llvm-objdump/Inputs/malformed-archives/libbogus1.a b/llvm/test/tools/llvm-objdump/Inputs/malformed-archives/libbogus1.a new file mode 100644 index 000000000000..510c1455527d --- /dev/null +++ b/llvm/test/tools/llvm-objdump/Inputs/malformed-archives/libbogus1.a @@ -0,0 +1,13 @@ +! +hello.c 1444941273 124 0 100644 10% ` +#include +#include +int +main() +{ + printf("Hello World\n"); + return EXIT_SUCCESS; +} +foo.c 1444941645 124 0 100644 1% ` +void foo(void){} + diff --git a/llvm/test/tools/llvm-objdump/Inputs/malformed-archives/libbogus2.a b/llvm/test/tools/llvm-objdump/Inputs/malformed-archives/libbogus2.a new file mode 100644 index 000000000000..2ccb7f31c09d --- /dev/null +++ b/llvm/test/tools/llvm-objdump/Inputs/malformed-archives/libbogus2.a @@ -0,0 +1,13 @@ +! +hello.c 1444941273 124 0 100644 102 ` +#include +#include +int +main() +{ + printf("Hello World\n"); + return EXIT_SUCCESS; +} +foo.c 1444941645 124 0 100644 1% ` +void foo(void){} + diff --git a/llvm/test/tools/llvm-objdump/Inputs/malformed-archives/libbogus3.a b/llvm/test/tools/llvm-objdump/Inputs/malformed-archives/libbogus3.a new file mode 100644 index 000000000000..f15a7329f9f4 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/Inputs/malformed-archives/libbogus3.a @@ -0,0 +1,16 @@ +! +hello.c 1444941273 124 0 100644 102 ` +#include +#include +int +main() +{ + printf("Hello World\n"); + return EXIT_SUCCESS; +} +foo.c 1444941645 124 0 100644 171 ` +void foo(void){} + +bar.c 1445026190 124 0 100644 17 ` +void foo(void){} + diff --git a/llvm/test/tools/llvm-objdump/malformed-archives.test b/llvm/test/tools/llvm-objdump/malformed-archives.test new file mode 100644 index 000000000000..5066cb543b4b --- /dev/null +++ b/llvm/test/tools/llvm-objdump/malformed-archives.test @@ -0,0 +1,20 @@ +// These test checks that llvm-objdump will not crash with malformed Archive +// files. So the check line is not all that important but the bug fixes to +// make sure llvm-objdump is robust is what matters. +# RUN: llvm-objdump -macho -archive-headers \ +# RUN: %p/Inputs/malformed-archives/libbogus1.a \ +# RUN: 2>&1 | FileCheck -check-prefix=bogus1 %s + +# bogus1: Invalid data was encountered while parsing the file + +# RUN: llvm-objdump -macho -archive-headers \ +# RUN: %p/Inputs/malformed-archives/libbogus2.a \ +# RUN: 2>&1 | FileCheck -check-prefix=bogus2 %s + +# bogus2: hello.c + +# RUN: llvm-objdump -macho -archive-headers \ +# RUN: %p/Inputs/malformed-archives/libbogus3.a \ +# RUN: 2>&1 | FileCheck -check-prefix=bogus3 %s + +# bogus3: foo.c diff --git a/llvm/tools/dsymutil/BinaryHolder.cpp b/llvm/tools/dsymutil/BinaryHolder.cpp index 7ff4fd699578..01a49c9b1ee3 100644 --- a/llvm/tools/dsymutil/BinaryHolder.cpp +++ b/llvm/tools/dsymutil/BinaryHolder.cpp @@ -109,7 +109,10 @@ BinaryHolder::GetArchiveMemberBuffers(StringRef Filename, Buffers.reserve(CurrentArchives.size()); for (const auto &CurrentArchive : CurrentArchives) { - for (const auto &Child : CurrentArchive->children()) { + for (auto ChildOrErr : CurrentArchive->children()) { + if (auto Err = ChildOrErr.getError()) + return Err; + const auto &Child = *ChildOrErr; if (auto NameOrErr = Child.getName()) { if (*NameOrErr == Filename) { if (Timestamp != sys::TimeValue::PosixZeroTime() && diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp index ec3cfcb5cad0..ec81421b4aeb 100644 --- a/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/llvm/tools/llvm-ar/llvm-ar.cpp @@ -338,7 +338,11 @@ static void doDisplayTable(StringRef Name, const object::Archive::Child &C) { printMode(Mode & 007); outs() << ' ' << C.getUID(); outs() << '/' << C.getGID(); - outs() << ' ' << format("%6llu", C.getSize()); + ErrorOr Size = C.getSize(); + if (Size.getError()) + outs() << ' ' << "bad size"; + else + outs() << ' ' << format("%6llu", Size.get()); outs() << ' ' << C.getLastModified().str(); outs() << ' '; } @@ -403,7 +407,14 @@ static void performReadOperation(ArchiveOperation Operation, } bool Filter = !Members.empty(); - for (const object::Archive::Child &C : OldArchive->children()) { + for (auto &ChildOrErr : OldArchive->children()) { + if (ChildOrErr.getError()) { + errs() << ToolName << ": error reading '" << ArchiveName + << "': " << ChildOrErr.getError().message() << "!\n"; + return; + } + const object::Archive::Child &C = *ChildOrErr; + ErrorOr NameOrErr = C.getName(); failIfError(NameOrErr.getError()); StringRef Name = NameOrErr.get(); @@ -448,7 +459,9 @@ void addMember(std::vector &Members, StringRef FileName, void addMember(std::vector &Members, object::Archive::child_iterator I, StringRef Name, int Pos = -1) { - if (Thin && !I->getParent()->isThin()) + if (I->getError()) + fail("New member is not valid: " + I->getError().message()); + if (Thin && !(*I)->getParent()->isThin()) fail("Cannot convert a regular archive to a thin one"); NewArchiveIterator NI(I, Name); if (Pos == -1) @@ -469,6 +482,9 @@ static InsertAction computeInsertAction(ArchiveOperation Operation, object::Archive::child_iterator I, StringRef Name, std::vector::iterator &Pos) { + if (I->getError()) + fail("Invalid member: " + I->getError().message()); + if (Operation == QuickAppend || Members.empty()) return IA_AddOldMember; @@ -500,7 +516,7 @@ static InsertAction computeInsertAction(ArchiveOperation Operation, // operation. sys::fs::file_status Status; failIfError(sys::fs::status(*MI, Status), *MI); - if (Status.getLastModificationTime() < I->getLastModified()) { + if (Status.getLastModificationTime() < (*I)->getLastModified()) { if (PosName.empty()) return IA_AddOldMember; return IA_MoveOldMember; @@ -523,7 +539,9 @@ computeNewArchiveMembers(ArchiveOperation Operation, int InsertPos = -1; StringRef PosName = sys::path::filename(RelPos); if (OldArchive) { - for (auto &Child : OldArchive->children()) { + for (auto &ChildOrErr : OldArchive->children()) { + failIfError(ChildOrErr.getError()); + auto &Child = ChildOrErr.get(); int Pos = Ret.size(); ErrorOr NameOrErr = Child.getName(); failIfError(NameOrErr.getError()); @@ -726,7 +744,9 @@ static void runMRIScript() { failIfError(LibOrErr.getError(), "Could not parse library"); Archives.push_back(std::move(*LibOrErr)); object::Archive &Lib = *Archives.back(); - for (auto &Member : Lib.children()) { + for (auto &MemberOrErr : Lib.children()) { + failIfError(MemberOrErr.getError()); + auto &Member = MemberOrErr.get(); ErrorOr NameOrErr = Member.getName(); failIfError(NameOrErr.getError()); addMember(NewMembers, Member, *NameOrErr); diff --git a/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp b/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp index d45a28a3b0f1..96526c4ea453 100644 --- a/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp +++ b/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp @@ -482,7 +482,12 @@ static void dumpCXXData(const ObjectFile *Obj) { } static void dumpArchive(const Archive *Arc) { - for (const Archive::Child &ArcC : Arc->children()) { + for (auto &ErrorOrChild : Arc->children()) { + if (std::error_code EC = ErrorOrChild.getError()) { + reportError(Arc->getFileName(), EC.message()); + break; + } + const Archive::Child &ArcC = *ErrorOrChild; ErrorOr> ChildOrErr = ArcC.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) { // Ignore non-object files. diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp index a0b5e9b4eaa4..fad9e582df0d 100644 --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -945,10 +945,11 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { if (I != E) { outs() << "Archive map\n"; for (; I != E; ++I) { - ErrorOr C = I->getMember(); - if (error(C.getError())) + ErrorOr ErrorOrChild = I->getMember(); + if (error(ErrorOrChild.getError())) return; - ErrorOr FileNameOrErr = C.get()->getName(); + auto &C = *(ErrorOrChild.get()); + ErrorOr FileNameOrErr = C.get().getName(); if (error(FileNameOrErr.getError())) return; StringRef SymName = I->getName(); @@ -960,7 +961,10 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E; ++I) { - ErrorOr> ChildOrErr = I->getAsBinary(&Context); + if (I->getError()) + break; + auto &C = I->get(); + ErrorOr> ChildOrErr = C.getAsBinary(&Context); if (ChildOrErr.getError()) continue; if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { @@ -1015,8 +1019,11 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { + if(AI->getError()) + break; + auto &C = AI->get(); ErrorOr> ChildOrErr = - AI->getAsBinary(&Context); + C.getAsBinary(&Context); if (ChildOrErr.getError()) continue; if (SymbolicFile *O = @@ -1069,8 +1076,11 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { + if(AI->getError()) + break; + auto &C = AI->get(); ErrorOr> ChildOrErr = - AI->getAsBinary(&Context); + C.getAsBinary(&Context); if (ChildOrErr.getError()) continue; if (SymbolicFile *O = @@ -1118,8 +1128,11 @@ static void dumpSymbolNamesFromFile(std::string &Filename) { std::unique_ptr &A = *AOrErr; for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { + if(AI->getError()) + continue; + auto &C = AI->get(); ErrorOr> ChildOrErr = - AI->getAsBinary(&Context); + C.getAsBinary(&Context); if (ChildOrErr.getError()) continue; if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp index 6b70c011c027..95869f2b952f 100644 --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/tools/llvm-objdump/MachODump.cpp @@ -1417,8 +1417,11 @@ static void printArchiveChild(Archive::Child &C, bool verbose, outs() << format("%3d/", UID); unsigned GID = C.getGID(); outs() << format("%-3d ", GID); - uint64_t Size = C.getRawSize(); - outs() << format("%5" PRId64, Size) << " "; + ErrorOr Size = C.getRawSize(); + if (Size.getError()) + outs() << "bad size" << " "; + else + outs() << format("%5" PRId64, Size.get()) << " "; StringRef RawLastModified = C.getRawLastModified(); if (verbose) { @@ -1454,12 +1457,16 @@ static void printArchiveChild(Archive::Child &C, bool verbose, static void printArchiveHeaders(Archive *A, bool verbose, bool print_offset) { if (A->hasSymbolTable()) { Archive::child_iterator S = A->getSymbolTableChild(); - Archive::Child C = *S; - printArchiveChild(C, verbose, print_offset); + if (!S->getError()) { + Archive::Child C = S->get(); + printArchiveChild(C, verbose, print_offset); + } } for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E; ++I) { - Archive::Child C = *I; + if(I->getError()) + break; + Archive::Child C = I->get(); printArchiveChild(C, verbose, print_offset); } } @@ -1496,7 +1503,10 @@ void llvm::ParseInputMachO(StringRef Filename) { printArchiveHeaders(A, !NonVerbose, ArchiveMemberOffsets); for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E; ++I) { - ErrorOr> ChildOrErr = I->getAsBinary(); + if (I->getError()) + break; + auto &C = I->get(); + ErrorOr> ChildOrErr = C.getAsBinary(); if (ChildOrErr.getError()) continue; if (MachOObjectFile *O = dyn_cast(&*ChildOrErr.get())) { @@ -1544,7 +1554,10 @@ void llvm::ParseInputMachO(StringRef Filename) { for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { - ErrorOr> ChildOrErr = AI->getAsBinary(); + if (AI->getError()) + break; + auto &C = AI->get(); + ErrorOr> ChildOrErr = C.getAsBinary(); if (ChildOrErr.getError()) continue; if (MachOObjectFile *O = @@ -1586,7 +1599,10 @@ void llvm::ParseInputMachO(StringRef Filename) { for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { - ErrorOr> ChildOrErr = AI->getAsBinary(); + if (AI->getError()) + break; + auto &C = AI->get(); + ErrorOr> ChildOrErr = C.getAsBinary(); if (ChildOrErr.getError()) continue; if (MachOObjectFile *O = @@ -1622,7 +1638,10 @@ void llvm::ParseInputMachO(StringRef Filename) { printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets); for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end(); AI != AE; ++AI) { - ErrorOr> ChildOrErr = AI->getAsBinary(); + if (AI->getError()) + break; + auto &C = AI->get(); + ErrorOr> ChildOrErr = C.getAsBinary(); if (ChildOrErr.getError()) continue; if (MachOObjectFile *O = diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 7292841c55a1..34401937bd80 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -1536,7 +1536,12 @@ static void DumpObject(const ObjectFile *o) { /// @brief Dump each object file in \a a; static void DumpArchive(const Archive *a) { - for (const Archive::Child &C : a->children()) { + for (auto &ErrorOrChild : a->children()) { + if (std::error_code EC = ErrorOrChild.getError()) { + report_error(a->getFileName(), EC); + break; + } + const Archive::Child &C = *ErrorOrChild; ErrorOr> ChildOrErr = C.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) if (EC != object_error::invalid_file_type) diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp index cb0c9c6418e6..b59579de49db 100644 --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -377,7 +377,12 @@ static void dumpObject(const ObjectFile *Obj) { /// @brief Dumps each object file in \a Arc; static void dumpArchive(const Archive *Arc) { - for (const auto &Child : Arc->children()) { + for (auto &ErrorOrChild : Arc->children()) { + if (std::error_code EC = ErrorOrChild.getError()) { + reportError(Arc->getFileName(), EC.message()); + break; + } + const auto &Child = *ErrorOrChild; ErrorOr> ChildOrErr = Child.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) { // Ignore non-object files. diff --git a/llvm/tools/llvm-size/llvm-size.cpp b/llvm/tools/llvm-size/llvm-size.cpp index de2b04505234..cc857624548a 100644 --- a/llvm/tools/llvm-size/llvm-size.cpp +++ b/llvm/tools/llvm-size/llvm-size.cpp @@ -427,7 +427,13 @@ static void PrintFileSectionSizes(StringRef file) { for (object::Archive::child_iterator i = a->child_begin(), e = a->child_end(); i != e; ++i) { - ErrorOr> ChildOrErr = i->getAsBinary(); + if (i->getError()) { + errs() << ToolName << ": " << file << ": " << i->getError().message() + << ".\n"; + break; + } + auto &c = i->get(); + ErrorOr> ChildOrErr = c.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) { errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; continue; @@ -489,7 +495,13 @@ static void PrintFileSectionSizes(StringRef file) { for (object::Archive::child_iterator i = UA->child_begin(), e = UA->child_end(); i != e; ++i) { - ErrorOr> ChildOrErr = i->getAsBinary(); + if (std::error_code EC = i->getError()) { + errs() << ToolName << ": " << file << ": " << EC.message() + << ".\n"; + break; + } + auto &c = i->get(); + ErrorOr> ChildOrErr = c.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) { errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; @@ -566,7 +578,13 @@ static void PrintFileSectionSizes(StringRef file) { for (object::Archive::child_iterator i = UA->child_begin(), e = UA->child_end(); i != e; ++i) { - ErrorOr> ChildOrErr = i->getAsBinary(); + if (std::error_code EC = i->getError()) { + errs() << ToolName << ": " << file << ": " << EC.message() + << ".\n"; + break; + } + auto &c = i->get(); + ErrorOr> ChildOrErr = c.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) { errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; @@ -630,7 +648,13 @@ static void PrintFileSectionSizes(StringRef file) { for (object::Archive::child_iterator i = UA->child_begin(), e = UA->child_end(); i != e; ++i) { - ErrorOr> ChildOrErr = i->getAsBinary(); + if (std::error_code EC = i->getError()) { + errs() << ToolName << ": " << file << ": " << EC.message() + << ".\n"; + break; + } + auto &c = i->get(); + ErrorOr> ChildOrErr = c.getAsBinary(); if (std::error_code EC = ChildOrErr.getError()) { errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; continue;