Skip to content

Commit

Permalink
[Object] Fix handling of large archive members
Browse files Browse the repository at this point in the history
The archive library truncated the size of archive members whose size was
greater than max uint32_t. This patch fixes the issue and adds some unit
tests to verify.

Reviewed by: ruiu, MaskRay, grimar, rupprecht

Differential Revision: https://reviews.llvm.org/D75742
  • Loading branch information
jh7370 committed Mar 11, 2020
1 parent a6d3bec commit 326bc1d
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 7 deletions.
10 changes: 3 additions & 7 deletions llvm/lib/Object/Archive.cpp
Expand Up @@ -392,12 +392,8 @@ Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
}

Expected<uint64_t> Archive::Child::getSize() const {
if (Parent->IsThin) {
Expected<uint32_t> Size = Header.getSize();
if (!Size)
return Size.takeError();
return Size.get();
}
if (Parent->IsThin)
return Header.getSize();
return Data.size() - StartOfFile;
}

Expand Down Expand Up @@ -437,7 +433,7 @@ Expected<StringRef> Archive::Child::getBuffer() const {
return isThinOrErr.takeError();
bool isThin = isThinOrErr.get();
if (!isThin) {
Expected<uint32_t> Size = getSize();
Expected<uint64_t> Size = getSize();
if (!Size)
return Size.takeError();
return StringRef(Data.data() + StartOfFile, Size.get());
Expand Down
81 changes: 81 additions & 0 deletions llvm/unittests/Object/ArchiveTest.cpp
@@ -0,0 +1,81 @@
//===- ArchiveTest.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/Object/Archive.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"

using namespace llvm;
using namespace object;
using namespace testing;

static const char ArchiveWithMember[] = "!<arch>\n" // Global header
"test/ " // Member name
"0 " // Timestamp
"0 " // Owner ID
"0 " // Group ID
"0 " // File mode
"9999999999" // Size
"`\n";

static const char ThinArchiveWithMember[] = "!<thin>\n" // Global header
"test/ " // Member name
"0 " // Timestamp
"0 " // Owner ID
"0 " // Group ID
"0 " // File mode
"9999999999" // Size
"`\n";

struct ArchiveTestsFixture : Test {
Expected<Archive::child_iterator> createChild(StringRef Src) {
MemoryBufferRef Source(Src, "archive");
Expected<std::unique_ptr<Archive>> AOrErr = Archive::create(Source);
if (!AOrErr)
return AOrErr.takeError();
A = std::move(*AOrErr);

Error ChildErr = Error::success();
auto Child = A->child_begin(ChildErr);
if (ChildErr)
return std::move(ChildErr);
return Child;
}

std::unique_ptr<Archive> A;
};

TEST_F(ArchiveTestsFixture, ArchiveChildGetSizeRegularArchive) {
auto Child = createChild(ArchiveWithMember);
ASSERT_THAT_EXPECTED(Child, Succeeded());

Expected<uint64_t> Size = (*Child)->getSize();
ASSERT_THAT_EXPECTED(Size, Succeeded());
EXPECT_EQ(9999999999, *Size);
}

TEST_F(ArchiveTestsFixture, ArchiveChildGetSizeThinArchive) {
auto Child = createChild(ThinArchiveWithMember);
ASSERT_THAT_EXPECTED(Child, Succeeded());

Expected<uint64_t> Size = (*Child)->getSize();
ASSERT_THAT_EXPECTED(Size, Succeeded());
EXPECT_EQ(9999999999, *Size);
}

TEST_F(ArchiveTestsFixture, ArchiveChildGetBuffer) {
auto Child = createChild(ArchiveWithMember);
ASSERT_THAT_EXPECTED(Child, Succeeded());

Expected<StringRef> Buffer = (*Child)->getBuffer();
// Cannot use ASSERT_THAT_EXPECTED, as that will attempt to print the
// StringRef (which has an invalid size).
ASSERT_TRUE((bool)Buffer);
EXPECT_EQ(9999999999, Buffer->size());
EXPECT_EQ(ArchiveWithMember + sizeof(ArchiveWithMember) - 1, Buffer->data());
}
1 change: 1 addition & 0 deletions llvm/unittests/Object/CMakeLists.txt
Expand Up @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
)

add_llvm_unittest(ObjectTests
ArchiveTest.cpp
MinidumpTest.cpp
ObjectFileTest.cpp
SymbolSizeTest.cpp
Expand Down

0 comments on commit 326bc1d

Please sign in to comment.