aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/archive/zip/reader.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/archive/zip/reader.go')
-rw-r--r--libgo/go/archive/zip/reader.go65
1 files changed, 49 insertions, 16 deletions
diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go
index f3826dcc48d..ddd507538b3 100644
--- a/libgo/go/archive/zip/reader.go
+++ b/libgo/go/archive/zip/reader.go
@@ -124,10 +124,6 @@ func (f *File) Open() (rc io.ReadCloser, err error) {
return
}
size := int64(f.CompressedSize)
- if size == 0 && f.hasDataDescriptor() {
- // permit SectionReader to see the rest of the file
- size = f.zipsize - (f.headerOffset + bodyOffset)
- }
r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, size)
switch f.Method {
case Store: // (no compression)
@@ -136,10 +132,13 @@ func (f *File) Open() (rc io.ReadCloser, err error) {
rc = flate.NewReader(r)
default:
err = ErrAlgorithm
+ return
}
- if rc != nil {
- rc = &checksumReader{rc, crc32.NewIEEE(), f, r}
+ var desr io.Reader
+ if f.hasDataDescriptor() {
+ desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen)
}
+ rc = &checksumReader{rc, crc32.NewIEEE(), f, desr, nil}
return
}
@@ -147,23 +146,36 @@ type checksumReader struct {
rc io.ReadCloser
hash hash.Hash32
f *File
- zipr io.Reader // for reading the data descriptor
+ 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) {
+ if r.err != nil {
+ return 0, r.err
+ }
n, err = r.rc.Read(b)
r.hash.Write(b[:n])
- if err != io.EOF {
+ if err == nil {
return
}
- if r.f.hasDataDescriptor() {
- if err = readDataDescriptor(r.zipr, r.f); err != nil {
- return
+ if err == io.EOF {
+ if r.desr != nil {
+ if err1 := readDataDescriptor(r.desr, r.f); err1 != nil {
+ err = err1
+ } else if r.hash.Sum32() != r.f.CRC32 {
+ err = ErrChecksum
+ }
+ } else {
+ // If there's not a data descriptor, we still compare
+ // the CRC32 of what we've read against the file header
+ // or TOC's CRC32, if it seems like it was set.
+ if r.f.CRC32 != 0 && r.hash.Sum32() != r.f.CRC32 {
+ err = ErrChecksum
+ }
}
}
- if r.hash.Sum32() != r.f.CRC32 {
- err = ErrChecksum
- }
+ r.err = err
return
}
@@ -226,10 +238,31 @@ func readDirectoryHeader(f *File, r io.Reader) error {
func readDataDescriptor(r io.Reader, f *File) error {
var buf [dataDescriptorLen]byte
- if _, err := io.ReadFull(r, buf[:]); err != nil {
+
+ // The spec says: "Although not originally assigned a
+ // signature, the value 0x08074b50 has commonly been adopted
+ // as a signature value for the data descriptor record.
+ // Implementers should be aware that ZIP files may be
+ // encountered with or without this signature marking data
+ // descriptors and should account for either case when reading
+ // ZIP files to ensure compatibility."
+ //
+ // dataDescriptorLen includes the size of the signature but
+ // first read just those 4 bytes to see if it exists.
+ if _, err := io.ReadFull(r, buf[:4]); err != nil {
return err
}
- b := readBuf(buf[:])
+ off := 0
+ maybeSig := readBuf(buf[:4])
+ if maybeSig.uint32() != dataDescriptorSignature {
+ // No data descriptor signature. Keep these four
+ // bytes.
+ off += 4
+ }
+ if _, err := io.ReadFull(r, buf[off:12]); err != nil {
+ return err
+ }
+ b := readBuf(buf[:12])
f.CRC32 = b.uint32()
f.CompressedSize = b.uint32()
f.UncompressedSize = b.uint32()