From 433c1ad1400047b17b9cd7107afa7afe55a04e12 Mon Sep 17 00:00:00 2001 From: Joe Shaw Date: Thu, 12 Feb 2015 17:21:01 -0500 Subject: [PATCH] archive/zip: fix size value in ZIP64 end central directory record Section 4.3.14.1 of the ZIP file format spec (https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT) says, The value stored into the "size of zip64 end of central directory record" should be the size of the remaining record and should not include the leading 12 bytes. We were previously writing the full size, including the 12 bytes. Fixes #9857 Change-Id: I7cf1fc8457c5f306717cbcf61e02304ab549781f Reviewed-on: https://go-review.googlesource.com/4760 Reviewed-by: Andrew Gerrand Reviewed-by: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick --- src/archive/zip/writer.go | 18 +++++++++--------- src/archive/zip/zip_test.go | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/archive/zip/writer.go b/src/archive/zip/writer.go index 170beec0ee..6a71887c63 100644 --- a/src/archive/zip/writer.go +++ b/src/archive/zip/writer.go @@ -122,15 +122,15 @@ func (w *Writer) Close() error { // zip64 end of central directory record b.uint32(directory64EndSignature) - b.uint64(directory64EndLen) - b.uint16(zipVersion45) // version made by - b.uint16(zipVersion45) // version needed to extract - b.uint32(0) // number of this disk - b.uint32(0) // number of the disk with the start of the central directory - b.uint64(records) // total number of entries in the central directory on this disk - b.uint64(records) // total number of entries in the central directory - b.uint64(size) // size of the central directory - b.uint64(offset) // offset of start of central directory with respect to the starting disk number + b.uint64(directory64EndLen - 12) // length minus signature (uint32) and length fields (uint64) + b.uint16(zipVersion45) // version made by + b.uint16(zipVersion45) // version needed to extract + b.uint32(0) // number of this disk + b.uint32(0) // number of the disk with the start of the central directory + b.uint64(records) // total number of entries in the central directory on this disk + b.uint64(records) // total number of entries in the central directory + b.uint64(size) // size of the central directory + b.uint64(offset) // offset of start of central directory with respect to the starting disk number // zip64 end of central directory locator b.uint32(directory64LocSignature) diff --git a/src/archive/zip/zip_test.go b/src/archive/zip/zip_test.go index 32a16a79ef..f00ff47d37 100644 --- a/src/archive/zip/zip_test.go +++ b/src/archive/zip/zip_test.go @@ -229,10 +229,11 @@ func TestZip64(t *testing.T) { t.Skip("slow test; skipping") } const size = 1 << 32 // before the "END\n" part - testZip64(t, size) + buf := testZip64(t, size) + testZip64DirectoryRecordLength(buf, t) } -func testZip64(t testing.TB, size int64) { +func testZip64(t testing.TB, size int64) *rleBuffer { const chunkSize = 1024 chunks := int(size / chunkSize) // write 2^32 bytes plus "END\n" to a zip file @@ -302,6 +303,37 @@ func testZip64(t testing.TB, size int64) { if got, want := f0.UncompressedSize64, uint64(size)+uint64(len(end)); got != want { t.Errorf("UncompressedSize64 %d, want %d", got, want) } + + return buf +} + +// Issue 9857 +func testZip64DirectoryRecordLength(buf *rleBuffer, t *testing.T) { + d := make([]byte, 1024) + if _, err := buf.ReadAt(d, buf.Size()-int64(len(d))); err != nil { + t.Fatal("read:", err) + } + + sigOff := findSignatureInBlock(d) + dirOff, err := findDirectory64End(buf, buf.Size()-int64(len(d))+int64(sigOff)) + if err != nil { + t.Fatal("findDirectory64End:", err) + } + + d = make([]byte, directory64EndLen) + if _, err := buf.ReadAt(d, dirOff); err != nil { + t.Fatal("read:", err) + } + + b := readBuf(d) + if sig := b.uint32(); sig != directory64EndSignature { + t.Fatalf("Expected directory64EndSignature (%d), got %d", directory64EndSignature, sig) + } + + size := b.uint64() + if size != directory64EndLen-12 { + t.Fatalf("Expected length of %d, got %d", directory64EndLen-12, size) + } } func testInvalidHeader(h *FileHeader, t *testing.T) { -- 2.48.1