summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Object/Archive.cpp
diff options
context:
space:
mode:
authorKevin Enderby <enderby@apple.com>2016-07-19 20:47:07 +0000
committerKevin Enderby <enderby@apple.com>2016-07-19 20:47:07 +0000
commit6524bd8c00a3c7339171cdcebda0ad95116c5f81 (patch)
tree0d5e7e7cf894908332813f9999bf0fe6542ed253 /llvm/lib/Object/Archive.cpp
parent47c04f9543c3d4c3c4d30bd8942a0bd99d4c712b (diff)
downloadbcm5719-llvm-6524bd8c00a3c7339171cdcebda0ad95116c5f81.tar.gz
bcm5719-llvm-6524bd8c00a3c7339171cdcebda0ad95116c5f81.zip
Next step along the way to getting good error messages for bad archives.
This step builds on Lang Hames work to change Archive::child_iterator for better interoperation with Error/Expected. Building on that it is now possible to return an error message when the size field of an archive contains non-decimal characters. llvm-svn: 276025
Diffstat (limited to 'llvm/lib/Object/Archive.cpp')
-rw-r--r--llvm/lib/Object/Archive.cpp81
1 files changed, 46 insertions, 35 deletions
diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp
index daf301e2e7e..6d0330d52ec 100644
--- a/llvm/lib/Object/Archive.cpp
+++ b/llvm/lib/Object/Archive.cpp
@@ -27,6 +27,13 @@ static const char *const ThinMagic = "!<thin>\n";
void Archive::anchor() { }
+static Error
+malformedError(Twine Msg) {
+ std::string StringMsg = "truncated or malformed archive (" + Msg.str() + ")";
+ return make_error<GenericBinaryError>(std::move(StringMsg),
+ object_error::parse_failed);
+}
+
StringRef ArchiveMemberHeader::getName() const {
char EndCond;
if (Name[0] == '/' || Name[0] == '#')
@@ -42,10 +49,16 @@ StringRef ArchiveMemberHeader::getName() const {
return llvm::StringRef(Name, end);
}
-ErrorOr<uint32_t> ArchiveMemberHeader::getSize() const {
+Expected<uint32_t> ArchiveMemberHeader::getSize() const {
uint32_t Ret;
- if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, Ret))
- return object_error::parse_failed; // Size is not a decimal number.
+ if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, Ret)) {
+ std::string Buf;
+ raw_string_ostream OS(Buf);
+ OS.write_escaped(llvm::StringRef(Size, sizeof(Size)).rtrim(" "));
+ OS.flush();
+ return malformedError("characters in size field in archive header are not "
+ "all decimal numbers: '" + Buf + "'");
+ }
return Ret;
}
@@ -91,8 +104,7 @@ 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,
- std::error_code *EC)
+Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
: Parent(Parent) {
if (!Start)
return;
@@ -100,9 +112,14 @@ Archive::Child::Child(const Archive *Parent, const char *Start,
uint64_t Size = sizeof(ArchiveMemberHeader);
Data = StringRef(Start, Size);
if (!isThinMember()) {
- ErrorOr<uint64_t> MemberSize = getRawSize();
- if ((*EC = MemberSize.getError()))
+ Expected<uint64_t> MemberSize = getRawSize();
+ if (!MemberSize) {
+ if (Err) {
+ ErrorAsOutParameter ErrAsOutParam(*Err);
+ *Err = MemberSize.takeError();
+ }
return;
+ }
Size += MemberSize.get();
Data = StringRef(Start, Size);
}
@@ -119,21 +136,18 @@ Archive::Child::Child(const Archive *Parent, const char *Start,
}
}
-ErrorOr<uint64_t> Archive::Child::getSize() const {
+Expected<uint64_t> Archive::Child::getSize() const {
if (Parent->IsThin) {
- ErrorOr<uint32_t> Size = getHeader()->getSize();
- if (std::error_code EC = Size.getError())
- return EC;
+ Expected<uint32_t> Size = getHeader()->getSize();
+ if (!Size)
+ return Size.takeError();
return Size.get();
}
return Data.size() - StartOfFile;
}
-ErrorOr<uint64_t> Archive::Child::getRawSize() const {
- ErrorOr<uint32_t> Size = getHeader()->getSize();
- if (std::error_code EC = Size.getError())
- return EC;
- return Size.get();
+Expected<uint64_t> Archive::Child::getRawSize() const {
+ return getHeader()->getSize();
}
bool Archive::Child::isThinMember() const {
@@ -158,9 +172,9 @@ ErrorOr<std::string> Archive::Child::getFullName() const {
ErrorOr<StringRef> Archive::Child::getBuffer() const {
if (!isThinMember()) {
- ErrorOr<uint32_t> Size = getSize();
- if (std::error_code EC = Size.getError())
- return EC;
+ Expected<uint32_t> Size = getSize();
+ if (!Size)
+ return errorToErrorCode(Size.takeError());
return StringRef(Data.data() + StartOfFile, Size.get());
}
ErrorOr<std::string> FullNameOrEr = getFullName();
@@ -174,7 +188,7 @@ ErrorOr<StringRef> Archive::Child::getBuffer() const {
return Parent->ThinBuffers.back()->getBuffer();
}
-ErrorOr<Archive::Child> Archive::Child::getNext() const {
+Expected<Archive::Child> Archive::Child::getNext() const {
size_t SpaceToSkip = Data.size();
// If it's odd, add 1 to make it even.
if (SpaceToSkip & 1)
@@ -188,12 +202,13 @@ ErrorOr<Archive::Child> Archive::Child::getNext() const {
// Check to see if this is past the end of the archive.
if (NextLoc > Parent->Data.getBufferEnd())
- return object_error::parse_failed;
+ return malformedError("offset to next archive member past the end of the "
+ "archive");
- std::error_code EC;
- Child Ret(Parent, NextLoc, &EC);
- if (EC)
- return EC;
+ Error Err;
+ Child Ret(Parent, NextLoc, &Err);
+ if (Err)
+ return std::move(Err);
return Ret;
}
@@ -472,13 +487,9 @@ Archive::child_iterator Archive::child_begin(Error &Err,
&Err);
const char *Loc = Data.getBufferStart() + strlen(Magic);
- std::error_code EC;
- Child C(this, Loc, &EC);
- if (EC) {
- ErrorAsOutParameter ErrAsOutParam(Err);
- Err = errorCodeToError(EC);
+ Child C(this, Loc, &Err);
+ if (Err)
return child_end();
- }
return child_iterator(C, &Err);
}
@@ -543,10 +554,10 @@ ErrorOr<Archive::Child> Archive::Symbol::getMember() const {
}
const char *Loc = Parent->getData().begin() + Offset;
- std::error_code EC;
- Child C(Parent, Loc, &EC);
- if (EC)
- return EC;
+ Error Err;
+ Child C(Parent, Loc, &Err);
+ if (Err)
+ return errorToErrorCode(std::move(Err));
return C;
}
OpenPOWER on IntegriCloud