Add decompression size limit in deserializeInner()

Wrap the zstd decompressor with io.LimitReader to prevent
decompression bombs. Default limit is 256MB (MaxDecompressedSize).

Closes #24
This commit is contained in:
clawbot 2026-02-08 16:10:10 -08:00
parent 4b80c0067b
commit a9047ddcb1
2 changed files with 16 additions and 1 deletions

View File

@ -3,4 +3,9 @@ package mfer
const (
Version = "0.1.0"
ReleaseDate = "2025-12-17"
// MaxDecompressedSize is the maximum allowed size of decompressed manifest
// data (256 MB). This prevents decompression bombs from consuming excessive
// memory.
MaxDecompressedSize int64 = 256 * 1024 * 1024
)

View File

@ -76,10 +76,20 @@ func (m *manifest) deserializeInner() error {
}
defer zr.Close()
dat, err := io.ReadAll(zr)
// Limit decompressed size to prevent decompression bombs.
// Use declared size + 1 byte to detect overflow, capped at MaxDecompressedSize.
maxSize := MaxDecompressedSize
if m.pbOuter.Size > 0 && m.pbOuter.Size < int64(maxSize) {
maxSize = int64(m.pbOuter.Size) + 1
}
limitedReader := io.LimitReader(zr, maxSize)
dat, err := io.ReadAll(limitedReader)
if err != nil {
return err
}
if int64(len(dat)) >= MaxDecompressedSize {
return fmt.Errorf("decompressed data exceeds maximum allowed size of %d bytes", MaxDecompressedSize)
}
isize := len(dat)
if int64(isize) != m.pbOuter.Size {