Skip to content

Commit 208df21

Browse files
committed
zip: only preallocate File slice if reasonably sized
Since the number of files in the EOCD record isn't validated, it isn't safe to preallocate Reader.Files using that field. A malformed archive can indicate it contains up to 1 << 128 - 1 files. We can still safely preallocate the slice by checking if the specified number of files in the archive is reasonable, given the size of the archive. Thanks to the OSS-Fuzz project for discovering this issue and to Emmanuel Odeke for reporting it. See golang/go#46242
1 parent 6315923 commit 208df21

File tree

1 file changed

+9
-1
lines changed

1 file changed

+9
-1
lines changed

zip/reader.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,15 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
8888
return fmt.Errorf("archive/zip: TOC declares impossible %d files in %d byte zip", end.directoryRecords, size)
8989
}
9090
z.r = r
91-
z.File = make([]*File, 0, end.directoryRecords)
91+
// Since the number of directory records is not validated, it is not
92+
// safe to preallocate z.File without first checking that the specified
93+
// number of files is reasonable, since a malformed archive may
94+
// indicate it contains up to 1 << 128 - 1 files. Since each file has a
95+
// header which will be _at least_ 30 bytes we can safely preallocate
96+
// if (data size / 30) >= end.directoryRecords.
97+
if (uint64(size)-end.directorySize)/30 >= end.directoryRecords {
98+
z.File = make([]*File, 0, end.directoryRecords)
99+
}
92100
z.Comment = end.comment
93101
rs := io.NewSectionReader(r, 0, size)
94102
if _, err = rs.Seek(int64(end.directoryOffset), io.SeekStart); err != nil {

0 commit comments

Comments
 (0)