Skip to content

Commit 9cf3e9a

Browse files
committed
Backport zip64 extra field improvements from Go's stdlib.
This fix allows zip to read archives that include files larger than 4GB and/or those that use zip64 extra fields. This is simply a backport of fixes that were made in http://golang.org/issue/13367.
1 parent 03d6312 commit 9cf3e9a

1 file changed

Lines changed: 24 additions & 4 deletions

File tree

reader.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,10 @@ func readDirectoryHeader(f *File, r io.Reader) error {
281281
f.Extra = d[filenameLen : filenameLen+extraLen]
282282
f.Comment = string(d[filenameLen+extraLen:])
283283

284+
needUSize := f.UncompressedSize == ^uint32(0)
285+
needCSize := f.CompressedSize == ^uint32(0)
286+
needHeaderOffset := f.headerOffset == int64(^uint32(0))
287+
284288
if len(f.Extra) > 0 {
285289
b := readBuf(f.Extra)
286290
for len(b) >= 4 { // need at least tag and size
@@ -290,16 +294,32 @@ func readDirectoryHeader(f *File, r io.Reader) error {
290294
return ErrFormat
291295
}
292296
eb := readBuf(b[:size])
297+
293298
switch tag {
294299
case zip64ExtraId:
295-
// update directory values from the zip64 extra block
296-
if len(eb) >= 8 {
300+
// update directory values from the zip64 extra block.
301+
// They should only be consulted if the sizes read earlier
302+
// are maxed out.
303+
// See golang.org/issue/13367.
304+
if needUSize {
305+
needUSize = false
306+
if len(eb) < 8 {
307+
return ErrFormat
308+
}
297309
f.UncompressedSize64 = eb.uint64()
298310
}
299-
if len(eb) >= 8 {
311+
if needCSize {
312+
needCSize = false
313+
if len(eb) < 8 {
314+
return ErrFormat
315+
}
300316
f.CompressedSize64 = eb.uint64()
301317
}
302-
if len(eb) >= 8 {
318+
if needHeaderOffset {
319+
needHeaderOffset = false
320+
if len(eb) < 8 {
321+
return ErrFormat
322+
}
303323
f.headerOffset = int64(eb.uint64())
304324
}
305325
case winzipAesExtraId:

0 commit comments

Comments
 (0)