@@ -13,14 +13,17 @@ import (
1313 "hash/crc32"
1414 "io"
1515 "os"
16+ "path/filepath"
17+ "strings"
1618 "time"
1719)
1820
1921var (
20- ErrFormat = errors .New ("zip: not a valid zip file" )
21- ErrAlgorithm = errors .New ("zip: unsupported compression algorithm" )
22- ErrChecksum = errors .New ("zip: checksum error" )
23- ErrEncrypted = errors .New ("zip: encrypted entries not supported" )
22+ ErrFormat = errors .New ("zip: not a valid zip file" )
23+ ErrAlgorithm = errors .New ("zip: unsupported compression algorithm" )
24+ ErrChecksum = errors .New ("zip: checksum error" )
25+ ErrEncrypted = errors .New ("zip: encrypted entries not supported" )
26+ ErrInsecurePath = errors .New ("zip: insecure file path" )
2427)
2528
2629type Reader struct {
@@ -70,6 +73,9 @@ func OpenReader(name string) (*ReadCloser, error) {
7073// NewReader returns a new Reader reading from r, which is assumed to
7174// have the given size in bytes.
7275func NewReader (r io.ReaderAt , size int64 ) (* Reader , error ) {
76+ if size < 0 {
77+ return nil , errors .New ("zip: size cannot be negative" )
78+ }
7379 zr := new (Reader )
7480 if err := zr .init (r , size ); err != nil {
7581 return nil , err
@@ -125,6 +131,18 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
125131 return err
126132 }
127133
134+ // Check for insecure file paths
135+ for _ , f := range z .File {
136+ if f .Name == "" {
137+ continue
138+ }
139+ // The zip specification states that names must use forward slashes,
140+ // so consider any backslashes in the name insecure.
141+ if ! filepath .IsLocal (f .Name ) || strings .Contains (f .Name , `\` ) {
142+ return ErrInsecurePath
143+ }
144+ }
145+
128146 return nil
129147}
130148
@@ -210,6 +228,9 @@ func (r *checksumReader) Read(b []byte) (n int, err error) {
210228 n , err = r .rc .Read (b )
211229 r .hash .Write (b [:n ])
212230 r .nread += uint64 (n )
231+ if r .nread > r .f .UncompressedSize64 {
232+ return 0 , ErrFormat
233+ }
213234 if err == nil {
214235 return
215236 }
0 commit comments