summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Object
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Object')
-rw-r--r--llvm/lib/Object/Archive.cpp134
-rw-r--r--llvm/lib/Object/ArchiveWriter.cpp7
2 files changed, 93 insertions, 48 deletions
diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp
index 5ac91f23035..99b0650c8b7 100644
--- a/llvm/lib/Object/Archive.cpp
+++ b/llvm/lib/Object/Archive.cpp
@@ -46,7 +46,7 @@ StringRef ArchiveMemberHeader::getName() const {
ErrorOr<uint32_t> 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;
}
@@ -86,7 +86,8 @@ Archive::Child::Child(const Archive *Parent, StringRef Data,
uint16_t StartOfFile)
: Parent(Parent), Data(Data), StartOfFile(StartOfFile) {}
-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;
@@ -94,7 +95,10 @@ Archive::Child::Child(const Archive *Parent, const char *Start)
uint64_t Size = sizeof(ArchiveMemberHeader);
Data = StringRef(Start, Size);
if (!isThinMember()) {
- Size += getRawSize();
+ ErrorOr<uint64_t> MemberSize = getRawSize();
+ if ((*EC = MemberSize.getError()))
+ return;
+ Size += MemberSize.get();
Data = StringRef(Start, Size);
}
@@ -110,20 +114,20 @@ Archive::Child::Child(const Archive *Parent, const char *Start)
}
}
-uint64_t Archive::Child::getSize() const {
+ErrorOr<uint64_t> Archive::Child::getSize() const {
if (Parent->IsThin) {
ErrorOr<uint32_t> 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<uint64_t> Archive::Child::getRawSize() const {
ErrorOr<uint32_t> Size = getHeader()->getSize();
- if (Size.getError())
- return 0;
+ if (std::error_code EC = Size.getError())
+ return EC;
return Size.get();
}
@@ -133,8 +137,12 @@ bool Archive::Child::isThinMember() const {
}
ErrorOr<StringRef> Archive::Child::getBuffer() const {
- if (!isThinMember())
- return StringRef(Data.data() + StartOfFile, getSize());
+ if (!isThinMember()) {
+ ErrorOr<uint32_t> Size = getSize();
+ if (std::error_code EC = Size.getError())
+ return EC;
+ return StringRef(Data.data() + StartOfFile, Size.get());
+ }
ErrorOr<StringRef> Name = getName();
if (std::error_code EC = Name.getError())
return EC;
@@ -148,7 +156,7 @@ ErrorOr<StringRef> Archive::Child::getBuffer() const {
return Parent->ThinBuffers.back()->getBuffer();
}
-Archive::Child Archive::Child::getNext() const {
+ErrorOr<Archive::Child> Archive::Child::getNext() const {
size_t SpaceToSkip = Data.size();
// If it's odd, add 1 to make it even.
if (SpaceToSkip & 1)
@@ -156,11 +164,19 @@ Archive::Child Archive::Child::getNext() const {
const char *NextLoc = Data.data() + SpaceToSkip;
+ // Check to see if this is at the end of the archive.
+ if (NextLoc == Parent->Data.getBufferEnd())
+ 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);
+ std::error_code EC;
+ Child Ret(Parent, NextLoc, &EC);
+ if (EC)
+ return EC;
+ return Ret;
}
uint64_t Archive::Child::getChildOffset() const {
@@ -255,15 +271,26 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
}
// Get the special members.
- child_iterator i = child_begin(false);
- child_iterator e = child_end();
+ child_iterator I = child_begin(false);
+ if ((ec = I->getError()))
+ return;
+ child_iterator E = child_end();
- if (i == e) {
+ if (I == E) {
ec = std::error_code();
return;
}
+ const Child *C = &**I;
- StringRef Name = i->getRawName();
+ auto Increment = [&]() {
+ ++I;
+ if ((ec = I->getError()))
+ return true;
+ C = &**I;
+ return false;
+ };
+
+ StringRef Name = C->getRawName();
// Below is the pattern that is used to figure out the archive format
// GNU archive format
@@ -288,9 +315,11 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
Format = K_BSD;
// We know that the symbol table is not an external file, so we just assert
// there is no error.
- SymbolTable = *i->getBuffer();
- ++i;
- setFirstRegular(*i);
+ SymbolTable = *C->getBuffer();
+ if (Increment())
+ return;
+ setFirstRegular(*C);
+
ec = std::error_code();
return;
}
@@ -298,7 +327,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<StringRef> NameOrErr = i->getName();
+ ErrorOr<StringRef> NameOrErr = C->getName();
ec = NameOrErr.getError();
if (ec)
return;
@@ -306,10 +335,11 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") {
// We know that the symbol table is not an external file, so we just
// assert there is no error.
- SymbolTable = *i->getBuffer();
- ++i;
+ SymbolTable = *C->getBuffer();
+ if (Increment())
+ return;
}
- setFirstRegular(*i);
+ setFirstRegular(*C);
return;
}
@@ -322,32 +352,34 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
if (Name == "/" || Name == "/SYM64/") {
// We know that the symbol table is not an external file, so we just assert
// there is no error.
- SymbolTable = *i->getBuffer();
+ SymbolTable = *C->getBuffer();
if (Name == "/SYM64/")
has64SymTable = true;
- ++i;
- if (i == e) {
+ if (Increment())
+ return;
+ if (I == E) {
ec = std::error_code();
return;
}
- Name = i->getRawName();
+ Name = C->getRawName();
}
if (Name == "//") {
Format = has64SymTable ? K_MIPS64 : K_GNU;
// The string table is never an external member, so we just assert on the
// ErrorOr.
- StringTable = *i->getBuffer();
- ++i;
- setFirstRegular(*i);
+ StringTable = *C->getBuffer();
+ if (Increment())
+ return;
+ setFirstRegular(*C);
ec = std::error_code();
return;
}
if (Name[0] != '/') {
Format = has64SymTable ? K_MIPS64 : K_GNU;
- setFirstRegular(*i);
+ setFirstRegular(*C);
ec = std::error_code();
return;
}
@@ -360,25 +392,28 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
Format = K_COFF;
// We know that the symbol table is not an external file, so we just assert
// there is no error.
- SymbolTable = *i->getBuffer();
+ SymbolTable = *C->getBuffer();
+
+ if (Increment())
+ return;
- ++i;
- if (i == e) {
- setFirstRegular(*i);
+ if (I == E) {
+ setFirstRegular(*C);
ec = std::error_code();
return;
}
- Name = i->getRawName();
+ Name = C->getRawName();
if (Name == "//") {
// The string table is never an external member, so we just assert on the
// ErrorOr.
- StringTable = *i->getBuffer();
- ++i;
+ StringTable = *C->getBuffer();
+ if (Increment())
+ return;
}
- setFirstRegular(*i);
+ setFirstRegular(*C);
ec = std::error_code();
}
@@ -390,12 +425,15 @@ Archive::child_iterator Archive::child_begin(bool SkipInternal) const {
return Child(this, FirstRegularData, FirstRegularStartOfFile);
const char *Loc = Data.getBufferStart() + strlen(Magic);
- Child c(this, Loc);
- return c;
+ std::error_code EC;
+ Child c(this, Loc, &EC);
+ if (EC)
+ return child_iterator(EC);
+ return child_iterator(c);
}
Archive::child_iterator Archive::child_end() const {
- return Child(this, nullptr);
+ return Child(this, nullptr, nullptr);
}
StringRef Archive::Symbol::getName() const {
@@ -447,7 +485,11 @@ ErrorOr<Archive::Child> Archive::Symbol::getMember() const {
}
const char *Loc = Parent->getData().begin() + Offset;
- return Child(Parent, Loc);
+ std::error_code EC;
+ Child C(Parent, Loc, &EC);
+ if (EC)
+ return EC;
+ return C;
}
Archive::Symbol Archive::Symbol::getNext() const {
diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp
index b68f7efa53c..f207dfb0876 100644
--- a/llvm/lib/Object/ArchiveWriter.cpp
+++ b/llvm/lib/Object/ArchiveWriter.cpp
@@ -39,7 +39,7 @@ NewArchiveIterator::NewArchiveIterator(const object::Archive::Child &OldMember,
: IsNewMember(false), Name(Name), OldMember(OldMember) {}
NewArchiveIterator::NewArchiveIterator(StringRef FileName)
- : IsNewMember(true), Name(FileName), OldMember(nullptr, nullptr) {}
+ : IsNewMember(true), Name(FileName), OldMember(nullptr, nullptr, nullptr) {}
StringRef NewArchiveIterator::getName() const { return Name; }
@@ -412,8 +412,11 @@ llvm::writeArchive(StringRef ArcName,
Status.getSize());
} else {
const object::Archive::Child &OldMember = I.getOld();
+ ErrorOr<uint32_t> 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)
OpenPOWER on IntegriCloud