Skip to content

Commit fad25c2

Browse files
committed
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 <bradfitz@golang.org> Reviewed-by: Andrew Gerrand <adg@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
1 parent b2f95a1 commit fad25c2

File tree

2 files changed

+58
-6
lines changed

2 files changed

+58
-6
lines changed

Diff for: src/archive/zip/reader.go

+16-6
Original file line numberDiff line numberDiff line change
@@ -146,16 +146,22 @@ func (f *File) Open() (rc io.ReadCloser, err error) {
146146
if f.hasDataDescriptor() {
147147
desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen)
148148
}
149-
rc = &checksumReader{rc, crc32.NewIEEE(), f, desr, nil}
149+
rc = &checksumReader{
150+
rc: rc,
151+
hash: crc32.NewIEEE(),
152+
f: f,
153+
desr: desr,
154+
}
150155
return
151156
}
152157

153158
type checksumReader struct {
154-
rc io.ReadCloser
155-
hash hash.Hash32
156-
f *File
157-
desr io.Reader // if non-nil, where to read the data descriptor
158-
err error // sticky error
159+
rc io.ReadCloser
160+
hash hash.Hash32
161+
nread uint64 // number of bytes read so far
162+
f *File
163+
desr io.Reader // if non-nil, where to read the data descriptor
164+
err error // sticky error
159165
}
160166

161167
func (r *checksumReader) Read(b []byte) (n int, err error) {
@@ -164,10 +170,14 @@ func (r *checksumReader) Read(b []byte) (n int, err error) {
164170
}
165171
n, err = r.rc.Read(b)
166172
r.hash.Write(b[:n])
173+
r.nread += uint64(n)
167174
if err == nil {
168175
return
169176
}
170177
if err == io.EOF {
178+
if r.nread != r.f.UncompressedSize64 {
179+
return 0, io.ErrUnexpectedEOF
180+
}
171181
if r.desr != nil {
172182
if err1 := readDataDescriptor(r.desr, r.f); err1 != nil {
173183
err = err1

Diff for: src/archive/zip/reader_test.go

+42
Original file line numberDiff line numberDiff line change
@@ -531,3 +531,45 @@ func TestIssue8186(t *testing.T) {
531531
}
532532
}
533533
}
534+
535+
// Verify we return ErrUnexpectedEOF when length is short.
536+
func TestIssue10957(t *testing.T) {
537+
data := []byte("PK\x03\x040000000PK\x01\x0200000" +
538+
"0000000000000000000\x00" +
539+
"\x00\x00\x00\x00\x00000000000000PK\x01" +
540+
"\x020000000000000000000" +
541+
"00000\v\x00\x00\x00\x00\x00000000000" +
542+
"00000000000000PK\x01\x0200" +
543+
"00000000000000000000" +
544+
"00\v\x00\x00\x00\x00\x00000000000000" +
545+
"00000000000PK\x01\x020000<" +
546+
"0\x00\x0000000000000000\v\x00\v" +
547+
"\x00\x00\x00\x00\x0000000000\x00\x00\x00\x00000" +
548+
"00000000PK\x01\x0200000000" +
549+
"0000000000000000\v\x00\x00\x00" +
550+
"\x00\x0000PK\x05\x06000000\x05\x000000" +
551+
"\v\x00\x00\x00\x00\x00")
552+
z, err := NewReader(bytes.NewReader(data), int64(len(data)))
553+
if err != nil {
554+
if z != nil {
555+
panic("non nil z")
556+
}
557+
return
558+
}
559+
for i, f := range z.File {
560+
r, err := f.Open()
561+
if err != nil {
562+
continue
563+
}
564+
if f.UncompressedSize64 < 1e6 {
565+
n, err := io.Copy(ioutil.Discard, r)
566+
if i == 3 && err != io.ErrUnexpectedEOF {
567+
t.Errorf("File[3] error = %v; want io.ErrUnexpectedEOF", err)
568+
}
569+
if err == nil && uint64(n) != f.UncompressedSize64 {
570+
t.Errorf("file %d: bad size: copied=%d; want=%d", i, n, f.UncompressedSize64)
571+
}
572+
}
573+
r.Close()
574+
}
575+
}

0 commit comments

Comments
 (0)