summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Object
diff options
context:
space:
mode:
authorOwen Reynolds <gbreynoo@gmail.com>2019-07-23 14:44:21 +0000
committerOwen Reynolds <gbreynoo@gmail.com>2019-07-23 14:44:21 +0000
commit24f3e102a678e2d102ac5660371fba1c2cfccd25 (patch)
tree8aae50fd303b854a6adb07b656efb2a5f53c1975 /llvm/lib/Object
parent4389cb9cf1b9493ad44bbfd97fe5d54450061988 (diff)
downloadbcm5719-llvm-24f3e102a678e2d102ac5660371fba1c2cfccd25.tar.gz
bcm5719-llvm-24f3e102a678e2d102ac5660371fba1c2cfccd25.zip
[llvm-ar] Fix support for archives with members larger than 4GB
llvm-ar outputs a strange error message when handling archives with members larger than 4GB due to not checking file size when passing the value as an unsigned 32 bit integer. This overflow issue caused malformed archives to be created.: https://bugs.llvm.org/show_bug.cgi?id=38058 This change allows for members above 4GB and will error in a case that is over the formats size limit, a 10 digit decimal integer. Differential Revision: https://reviews.llvm.org/D65093 llvm-svn: 366813
Diffstat (limited to 'llvm/lib/Object')
-rw-r--r--llvm/lib/Object/Archive.cpp4
-rw-r--r--llvm/lib/Object/ArchiveWriter.cpp21
2 files changed, 17 insertions, 8 deletions
diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp
index 49e66f46ab3..fd9609f65bc 100644
--- a/llvm/lib/Object/Archive.cpp
+++ b/llvm/lib/Object/Archive.cpp
@@ -223,8 +223,8 @@ Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const {
return Name.drop_back(1);
}
-Expected<uint32_t> ArchiveMemberHeader::getSize() const {
- uint32_t Ret;
+Expected<uint64_t> ArchiveMemberHeader::getSize() const {
+ uint64_t Ret;
if (StringRef(ArMemHdr->Size,
sizeof(ArMemHdr->Size)).rtrim(" ").getAsInteger(10, Ret)) {
std::string Buf;
diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp
index 228f6b40c5e..f12f1e521a9 100644
--- a/llvm/lib/Object/ArchiveWriter.cpp
+++ b/llvm/lib/Object/ArchiveWriter.cpp
@@ -16,6 +16,7 @@
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/Archive.h"
+#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/EndianStream.h"
@@ -147,7 +148,7 @@ static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val) {
static void printRestOfMemberHeader(
raw_ostream &Out, const sys::TimePoint<std::chrono::seconds> &ModTime,
- unsigned UID, unsigned GID, unsigned Perms, unsigned Size) {
+ unsigned UID, unsigned GID, unsigned Perms, uint64_t Size) {
printWithSpacePadding(Out, sys::toTimeT(ModTime), 12);
// The format has only 6 chars for uid and gid. Truncate if the provided
@@ -164,7 +165,7 @@ static void
printGNUSmallMemberHeader(raw_ostream &Out, StringRef Name,
const sys::TimePoint<std::chrono::seconds> &ModTime,
unsigned UID, unsigned GID, unsigned Perms,
- unsigned Size) {
+ uint64_t Size) {
printWithSpacePadding(Out, Twine(Name) + "/", 16);
printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
}
@@ -172,8 +173,7 @@ printGNUSmallMemberHeader(raw_ostream &Out, StringRef Name,
static void
printBSDMemberHeader(raw_ostream &Out, uint64_t Pos, StringRef Name,
const sys::TimePoint<std::chrono::seconds> &ModTime,
- unsigned UID, unsigned GID, unsigned Perms,
- unsigned Size) {
+ unsigned UID, unsigned GID, unsigned Perms, uint64_t Size) {
uint64_t PosAfterHeader = Pos + 60 + Name.size();
// Pad so that even 64 bit object files are aligned.
unsigned Pad = OffsetToAlignment(PosAfterHeader, 8);
@@ -208,7 +208,7 @@ static void
printMemberHeader(raw_ostream &Out, uint64_t Pos, raw_ostream &StringTable,
StringMap<uint64_t> &MemberNames, object::Archive::Kind Kind,
bool Thin, const NewArchiveMember &M,
- sys::TimePoint<std::chrono::seconds> ModTime, unsigned Size) {
+ sys::TimePoint<std::chrono::seconds> ModTime, uint64_t Size) {
if (isBSDLike(Kind))
return printBSDMemberHeader(Out, Pos, M.MemberName, ModTime, M.UID, M.GID,
M.Perms, Size);
@@ -474,8 +474,17 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
ModTime = sys::toTimePoint(FilenameCount[M.MemberName]++);
else
ModTime = M.ModTime;
+
+ uint64_t Size = Buf.getBufferSize() + MemberPadding;
+ if (Size > object::Archive::MaxMemberSize) {
+ std::string StringMsg =
+ "File " + M.MemberName.str() + " exceeds size limit";
+ return make_error<object::GenericBinaryError>(
+ std::move(StringMsg), object::object_error::parse_failed);
+ }
+
printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M,
- ModTime, Buf.getBufferSize() + MemberPadding);
+ ModTime, Size);
Out.flush();
Expected<std::vector<unsigned>> Symbols =
OpenPOWER on IntegriCloud