From 7f0003c19c3a47f484ea9cc929728808b27ace32 Mon Sep 17 00:00:00 2001 From: Kai Luo Date: Mon, 30 Jan 2023 13:43:50 +0800 Subject: [PATCH] [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 --- llvm/include/llvm/Object/Archive.h | 4 +--- llvm/lib/Object/Archive.cpp | 10 +++++++++- llvm/test/Object/archive-big-malformed-first-member.test | 7 +++++++ llvm/test/Object/archive-big-read-empty-with-freelist.test | 4 ++-- 4 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 llvm/test/Object/archive-big-malformed-first-member.test diff --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h index fbacee9..b77c853 100644 --- a/llvm/include/llvm/Object/Archive.h +++ b/llvm/include/llvm/Object/Archive.h @@ -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 diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp index 2cf9241..046bcb3 100644 --- a/llvm/lib/Object/Archive.cpp +++ b/llvm/lib/Object/Archive.cpp @@ -949,7 +949,15 @@ Archive::child_iterator Archive::child_begin(Error &Err, return child_iterator::itr( Child(this, FirstRegularData, FirstRegularStartOfFile), Err); - const char *Loc = Data.getBufferStart() + getFirstChildOffset(); + uint64_t FirstChildOffset = getFirstChildOffset(); + const char *Loc = Data.getBufferStart() + FirstChildOffset; + if (Loc >= Data.getBufferEnd()) { + Err = malformedError("First member offset " + Twine(FirstChildOffset) + + " is beyond the data buffer which has size of " + + Twine(Data.getBufferSize())); + return child_end(); + } + Child C(this, Loc, &Err); if (Err) return child_end(); 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 0000000..08ae37b --- /dev/null +++ b/llvm/test/Object/archive-big-malformed-first-member.test @@ -0,0 +1,7 @@ +# Test reading an empty archive with first member's offset is not zero. +# RUN: echo "" > %t.a +# RUN: echo -n "0 0 0 128 0 0 " >> %t.a +# RUN: not llvm-ar tv %t.a 2>&1 | grep 'truncated or malformed archive' +# RUN: echo "" > %t.a +# RUN: echo -n "0 0 0 28 0 0 " >> %t.a +# RUN: not llvm-ar tv %t.a 2>&1 | grep 'truncated or malformed archive' 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 2ac3253..05e45ca 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' +# RUN: llvm-ar tv %p/Inputs/aix-empty-big-archive-with-freelist.a 2>&1 \ +# RUN: | not grep 'truncated or malformed archive' -- 2.7.4