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

Kai Luo via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 6 00:33:45 PST 2023


Author: Kai Luo
Date: 2023-03-06T16:33:27+08:00
New Revision: c0d9e5a0a4b80b0740282649ea32b0422e45e9ee

URL: https://github.com/llvm/llvm-project/commit/c0d9e5a0a4b80b0740282649ea32b0422e45e9ee
DIFF: https://github.com/llvm/llvm-project/commit/c0d9e5a0a4b80b0740282649ea32b0422e45e9ee.diff

LOG: 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

Added: 
    llvm/test/Object/archive-big-malformed-first-member.test

Modified: 
    llvm/include/llvm/Object/Archive.h
    llvm/lib/Object/Archive.cpp
    llvm/test/Object/archive-big-read-empty-with-freelist.test

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h
index fbacee964aa88..b77c8537eeaa0 100644
--- a/llvm/include/llvm/Object/Archive.h
+++ b/llvm/include/llvm/Object/Archive.h
@@ -410,9 +410,7 @@ class BigArchive : public Archive {
   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

diff  --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp
index f4d2ff2e625fe..52d0dafd07e4c 100644
--- a/llvm/lib/Object/Archive.cpp
+++ b/llvm/lib/Object/Archive.cpp
@@ -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) {

diff  --git a/llvm/test/Object/archive-big-malformed-first-member.test b/llvm/test/Object/archive-big-malformed-first-member.test
new file mode 100644
index 0000000000000..e38edc699d9db
--- /dev/null
+++ b/llvm/test/Object/archive-big-malformed-first-member.test
@@ -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

diff  --git a/llvm/test/Object/archive-big-read-empty-with-freelist.test b/llvm/test/Object/archive-big-read-empty-with-freelist.test
index 2ac3253446597..e9af7e0f81425 100644
--- a/llvm/test/Object/archive-big-read-empty-with-freelist.test
+++ b/llvm/test/Object/archive-big-read-empty-with-freelist.test
@@ -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


        


More information about the llvm-commits mailing list