mirror of
https://github.com/golang/go
synced 2024-11-18 10:54:40 -07:00
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>
This commit is contained in:
parent
b2f95a167a
commit
fad25c29a1
@ -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
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user