]> Cypherpunks repositories - gostls13.git/commitdiff
archive/zip: verify number of File bytes read at EOF
authorBrad Fitzpatrick <bradfitz@golang.org>
Tue, 26 May 2015 20:49:55 +0000 (13:49 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Tue, 26 May 2015 22:18:21 +0000 (22:18 +0000)
Fixes #10957

Change-Id: I75fe25133dfcebd1682a8058b1c354ec894cc997
Reviewed-on: https://go-review.googlesource.com/10384
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/archive/zip/reader.go
src/archive/zip/reader_test.go

index 8136b840d455f4bcf0911d1c0b7020822a49faba..10d9d5e5bf071e966527462229d0e176093fa91c 100644 (file)
@@ -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
index 29d0652dcc16ed795841f9449aecb4d1a0f0caa3..6a8cab34cde8440ce332b8faa59d1c7f92239a4d 100644 (file)
@@ -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()
+       }
+}