Skip to content

Commit

Permalink
internal/zstd: avoid panic when the regenerated size is too small
Browse files Browse the repository at this point in the history
The decompressed size of each stream is equal to (Regenerated_Size+3)/4,
except for the last stream, which may be up to 3 bytes smaller,
to reach a total decompressed size as specified in Regenerated_Size.

Fixes golang#63824
  • Loading branch information
aimuz committed Nov 8, 2023
1 parent 4cd201b commit 9f8542d
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/internal/zstd/fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ var badStrings = []string{
"(\xb5/\xfd\x1002000$\x05\x0010\xcc0\xa8100000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"(\xb5/\xfd\x1002000$\x05\x0000\xcc0\xa8100d\x0000001000000000000000000000000000000000000000000000000000000000000000000000000\x000000000000000000000000000000000000000000000000000000000000000000000000000000",
"(\xb5/\xfd001\x00\x0000000000000000000",
"(\xb5/\xfd00\xec\x00\x00&@\x05\x05A7002\x02\x00\x02\x00\x02\x0000000000000000",
"(\xb5/\xfd00\xec\x00\x00V@\x05\x0517002\x02\x00\x02\x00\x02\x0000000000000000",
}

// This is a simple fuzzer to see if the decompressor panics.
Expand Down
10 changes: 8 additions & 2 deletions src/internal/zstd/literals.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,14 @@ func (r *Reader) readLiteralsFourStreams(data block, off, totalStreamsSize, rege
if totalStreamsSize < 6 {
return nil, r.makeError(off, "total streams size too small for jump table")
}
// RFC 8878 3.1.1.3.1.6.
// The decompressed size of each stream is equal to (Regenerated_Size+3)/4,
// except for the last stream, which may be up to 3 bytes smaller,
// to reach a total decompressed size as specified in Regenerated_Size.
regeneratedStreamSize := (regeneratedSize + 3) / 4
if regeneratedSize < regeneratedStreamSize*3 {
return nil, r.makeError(off, "regenerated size too small for output")
}

streamSize1 := binary.LittleEndian.Uint16(data[off:])
streamSize2 := binary.LittleEndian.Uint16(data[off+2:])
Expand Down Expand Up @@ -262,8 +270,6 @@ func (r *Reader) readLiteralsFourStreams(data block, off, totalStreamsSize, rege
return nil, err
}

regeneratedStreamSize := (regeneratedSize + 3) / 4

out1 := len(outbuf)
out2 := out1 + regeneratedStreamSize
out3 := out2 + regeneratedStreamSize
Expand Down

0 comments on commit 9f8542d

Please sign in to comment.