Reland [AIX][BigArchive] Treat the archive is empty if the first child member offset is zero

If the archive contains free list and contains no member file, the buffer length doesn't equal to length of the header.

Reviewed By: Esme, DiggerLin, #powerpc

Differential Revision: https://reviews.llvm.org/D138986
This commit is contained in:
Kai Luo 2023-03-06 16:01:24 +08:00
parent 29a4ed80bb
commit c0d9e5a0a4
4 changed files with 34 additions and 7 deletions

View File

@ -410,9 +410,7 @@ public:
BigArchive(MemoryBufferRef Source, Error &Err);
uint64_t getFirstChildOffset() const override { return FirstChildOffset; }
uint64_t getLastChildOffset() const { return LastChildOffset; }
bool isEmpty() const override {
return Data.getBufferSize() == sizeof(FixLenHdr);
};
bool isEmpty() const override { return getFirstChildOffset() == 0; }
};
} // end namespace object

View File

@ -135,6 +135,13 @@ BigArchiveMemberHeader::BigArchiveMemberHeader(const Archive *Parent,
return;
ErrorAsOutParameter ErrAsOutParam(Err);
if (RawHeaderPtr + getSizeOf() >= Parent->getData().end()) {
if (Err)
*Err = malformedError("malformed AIX big archive: remaining buffer is "
"unable to contain next archive member");
return;
}
if (Size < getSizeOf()) {
Error SubErr = createMemberHeaderParseError(this, RawHeaderPtr, Size);
if (Err)
@ -1172,6 +1179,14 @@ BigArchive::BigArchive(MemoryBufferRef Source, Error &Err)
ErrorAsOutParameter ErrAsOutParam(&Err);
StringRef Buffer = Data.getBuffer();
ArFixLenHdr = reinterpret_cast<const FixLenHdr *>(Buffer.data());
uint64_t BufferSize = Data.getBufferSize();
if (BufferSize < sizeof(FixLenHdr)) {
Err = malformedError("malformed AIX big archive: incomplete fixed length "
"header, the archive is only" +
Twine(BufferSize) + " byte(s)");
return;
}
StringRef RawOffset = getFieldRawString(ArFixLenHdr->FirstChildOffset);
if (RawOffset.getAsInteger(10, FirstChildOffset))
@ -1198,7 +1213,6 @@ BigArchive::BigArchive(MemoryBufferRef Source, Error &Err)
return;
if (GlobSymOffset > 0) {
uint64_t BufferSize = Data.getBufferSize();
uint64_t GlobalSymTblContentOffset =
GlobSymOffset + sizeof(BigArMemHdrType);
if (GlobalSymTblContentOffset > BufferSize) {

View File

@ -0,0 +1,15 @@
## Test reading an archive with malformed header.
# RUN: echo "<bigaf>" > %t.a
# RUN: not llvm-ar tv %t.a 2>&1 | FileCheck --check-prefix=CHECK-HEADER %s
# CHECK-HEADER: truncated or malformed archive{{.*}}malformed AIX big archive: incomplete fixed length header
## Test reading an empty archive with first member's offset is not zero.
# RUN: echo "<bigaf>" > %t.a
# RUN: echo -n "0 0 0 128 0 0 " >> %t.a
# RUN: not llvm-ar tv %t.a 2>&1 | FileCheck %s
# RUN: echo "<bigaf>" > %t.a
# RUN: echo -n "0 0 0 28 0 0 " >> %t.a
# RUN: not llvm-ar tv %t.a 2>&1 | FileCheck %s
# CHECK: truncated or malformed archive{{.*}}malformed AIX big archive: remaining buffer is unable to contain next archive member

View File

@ -1,3 +1,3 @@
# Test reading an empty archive with free list in it.
# RUN: not llvm-ar tv %p/Inputs/aix-empty-big-archive-with-freelist.a 2>&1 \
# RUN: | grep 'truncated or malformed archive'
## Test reading an empty archive with free list in it, should exit normally.
# RUN: llvm-ar tv %p/Inputs/aix-empty-big-archive-with-freelist.a 2>&1 \
# RUN: | count 0