From: Brad Fitzpatrick Date: Tue, 26 May 2015 20:49:55 +0000 (-0700) Subject: archive/zip: verify number of File bytes read at EOF X-Git-Tag: go1.5beta1~472 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=fad25c29a1c8c3cffdd18ff8ebff3ead3bdfed1f;p=gostls13.git archive/zip: verify number of File bytes read at EOF Fixes #10957 Change-Id: I75fe25133dfcebd1682a8058b1c354ec894cc997 Reviewed-on: https://go-review.googlesource.com/10384 Run-TryBot: Brad Fitzpatrick Reviewed-by: Andrew Gerrand TryBot-Result: Gobot Gobot --- diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go index 8136b840d4..10d9d5e5bf 100644 --- a/src/archive/zip/reader.go +++ b/src/archive/zip/reader.go @@ -146,16 +146,22 @@ func (f *File) Open() (rc io.ReadCloser, err error) { if f.hasDataDescriptor() { desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen) } - rc = &checksumReader{rc, crc32.NewIEEE(), f, desr, nil} + rc = &checksumReader{ + rc: rc, + hash: crc32.NewIEEE(), + f: f, + desr: desr, + } return } type checksumReader struct { - rc io.ReadCloser - hash hash.Hash32 - f *File - desr io.Reader // if non-nil, where to read the data descriptor - err error // sticky error + rc io.ReadCloser + hash hash.Hash32 + nread uint64 // number of bytes read so far + f *File + desr io.Reader // if non-nil, where to read the data descriptor + err error // sticky error } func (r *checksumReader) Read(b []byte) (n int, err error) { @@ -164,10 +170,14 @@ func (r *checksumReader) Read(b []byte) (n int, err error) { } n, err = r.rc.Read(b) r.hash.Write(b[:n]) + r.nread += uint64(n) if err == nil { return } if err == io.EOF { + if r.nread != r.f.UncompressedSize64 { + return 0, io.ErrUnexpectedEOF + } if r.desr != nil { if err1 := readDataDescriptor(r.desr, r.f); err1 != nil { err = err1 diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go index 29d0652dcc..6a8cab34cd 100644 --- a/src/archive/zip/reader_test.go +++ b/src/archive/zip/reader_test.go @@ -531,3 +531,45 @@ func TestIssue8186(t *testing.T) { } } } + +// Verify we return ErrUnexpectedEOF when length is short. +func TestIssue10957(t *testing.T) { + data := []byte("PK\x03\x040000000PK\x01\x0200000" + + "0000000000000000000\x00" + + "\x00\x00\x00\x00\x00000000000000PK\x01" + + "\x020000000000000000000" + + "00000\v\x00\x00\x00\x00\x00000000000" + + "00000000000000PK\x01\x0200" + + "00000000000000000000" + + "00\v\x00\x00\x00\x00\x00000000000000" + + "00000000000PK\x01\x020000<" + + "0\x00\x0000000000000000\v\x00\v" + + "\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00000" + + "00000000PK\x01\x0200000000" + + "0000000000000000\v\x00\x00\x00" + + "\x00\x0000PK\x05\x06000000\x05\x000000" + + "\v\x00\x00\x00\x00\x00") + z, err := NewReader(bytes.NewReader(data), int64(len(data))) + if err != nil { + if z != nil { + panic("non nil z") + } + return + } + for i, f := range z.File { + r, err := f.Open() + if err != nil { + continue + } + if f.UncompressedSize64 < 1e6 { + n, err := io.Copy(ioutil.Discard, r) + if i == 3 && err != io.ErrUnexpectedEOF { + t.Errorf("File[3] error = %v; want io.ErrUnexpectedEOF", err) + } + if err == nil && uint64(n) != f.UncompressedSize64 { + t.Errorf("file %d: bad size: copied=%d; want=%d", i, n, f.UncompressedSize64) + } + } + r.Close() + } +}