Skip to content

Commit 5a16edc

Browse files
authored
gzip: fix stack exhaustion bug in Reader.Read (#641)
Replace recursion with iteration in Reader.Read to avoid stack exhaustion when there are a large number of files. Fixes CVE-2022-30631 Upstream: golang/go#53168
1 parent 9a048c1 commit 5a16edc

File tree

1 file changed

+29
-31
lines changed

1 file changed

+29
-31
lines changed

gzip/gunzip.go

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -252,42 +252,40 @@ func (z *Reader) Read(p []byte) (n int, err error) {
252252
return 0, z.err
253253
}
254254

255-
n, z.err = z.decompressor.Read(p)
256-
z.digest = crc32.Update(z.digest, crc32.IEEETable, p[:n])
257-
z.size += uint32(n)
258-
if z.err != io.EOF {
259-
// In the normal case we return here.
260-
return n, z.err
261-
}
255+
for n == 0 {
256+
n, z.err = z.decompressor.Read(p)
257+
z.digest = crc32.Update(z.digest, crc32.IEEETable, p[:n])
258+
z.size += uint32(n)
259+
if z.err != io.EOF {
260+
// In the normal case we return here.
261+
return n, z.err
262+
}
262263

263-
// Finished file; check checksum and size.
264-
if _, err := io.ReadFull(z.r, z.buf[:8]); err != nil {
265-
z.err = noEOF(err)
266-
return n, z.err
267-
}
268-
digest := le.Uint32(z.buf[:4])
269-
size := le.Uint32(z.buf[4:8])
270-
if digest != z.digest || size != z.size {
271-
z.err = ErrChecksum
272-
return n, z.err
273-
}
274-
z.digest, z.size = 0, 0
264+
// Finished file; check checksum and size.
265+
if _, err := io.ReadFull(z.r, z.buf[:8]); err != nil {
266+
z.err = noEOF(err)
267+
return n, z.err
268+
}
269+
digest := le.Uint32(z.buf[:4])
270+
size := le.Uint32(z.buf[4:8])
271+
if digest != z.digest || size != z.size {
272+
z.err = ErrChecksum
273+
return n, z.err
274+
}
275+
z.digest, z.size = 0, 0
275276

276-
// File is ok; check if there is another.
277-
if !z.multistream {
278-
return n, io.EOF
279-
}
280-
z.err = nil // Remove io.EOF
277+
// File is ok; check if there is another.
278+
if !z.multistream {
279+
return n, io.EOF
280+
}
281+
z.err = nil // Remove io.EOF
281282

282-
if _, z.err = z.readHeader(); z.err != nil {
283-
return n, z.err
283+
if _, z.err = z.readHeader(); z.err != nil {
284+
return n, z.err
285+
}
284286
}
285287

286-
// Read from next file, if necessary.
287-
if n > 0 {
288-
return n, nil
289-
}
290-
return z.Read(p)
288+
return n, nil
291289
}
292290

293291
// Support the io.WriteTo interface for io.Copy and friends.

0 commit comments

Comments
 (0)