From: aimuz Date: Thu, 9 Nov 2023 02:30:46 +0000 (+0000) Subject: internal/zstd: avoid panic when the regenerated size is too small X-Git-Tag: go1.22rc1~373 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=291ffcbea6fb8c90681d80c2d708402df00633f9;p=gostls13.git internal/zstd: avoid panic when the regenerated size is too small Description in accordance with 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. Fixes #63824 Change-Id: I5a8b482a995272aa2028a81a4db86c21b1770432 GitHub-Last-Rev: 76a70756bc005a8fcd33b4b6a50fd6c3bf827fb6 GitHub-Pull-Request: golang/go#63959 Reviewed-on: https://go-review.googlesource.com/c/go/+/540055 Auto-Submit: Bryan Mills Reviewed-by: Matthew Dempsky Reviewed-by: Bryan Mills Reviewed-by: Klaus Post Run-TryBot: Jes Cok TryBot-Result: Gopher Robot --- diff --git a/src/internal/zstd/fuzz_test.go b/src/internal/zstd/fuzz_test.go index 12738519f8..4c0e9cf7b9 100644 --- a/src/internal/zstd/fuzz_test.go +++ b/src/internal/zstd/fuzz_test.go @@ -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. diff --git a/src/internal/zstd/literals.go b/src/internal/zstd/literals.go index b46d668f26..11ef859f14 100644 --- a/src/internal/zstd/literals.go +++ b/src/internal/zstd/literals.go @@ -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 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 to decode streams") + } streamSize1 := binary.LittleEndian.Uint16(data[off:]) streamSize2 := binary.LittleEndian.Uint16(data[off+2:]) @@ -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