diff --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h --- a/llvm/include/llvm/Object/Archive.h +++ b/llvm/include/llvm/Object/Archive.h @@ -410,9 +410,7 @@ 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 --- a/llvm/lib/Object/Archive.cpp +++ b/llvm/lib/Object/Archive.cpp @@ -949,7 +949,15 @@ 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 --- /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 --- 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'