From ab0be6578247da896f16d85e102b81994b8ee5c4 Mon Sep 17 00:00:00 2001 From: aimuz Date: Tue, 7 Nov 2023 17:38:56 +0800 Subject: [PATCH] internal/zstd: avoid panic when windowSize is negative Consistency of Window_Size and Frame_Content_Size value ranges as per RFC 8878 3.1.1.1.2 to resolve panic issues. Fixes #63979 --- src/internal/zstd/fuzz_test.go | 1 + src/internal/zstd/zstd.go | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/internal/zstd/fuzz_test.go b/src/internal/zstd/fuzz_test.go index 4b5c9961d87..e945f412415 100644 --- a/src/internal/zstd/fuzz_test.go +++ b/src/internal/zstd/fuzz_test.go @@ -25,6 +25,7 @@ var badStrings = []string{ "(\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", "\x50\x2a\x4d\x18\x02\x00\x00\x00", + "(\xb5/\xfd\xe40000000\xfa20\x000", } // This is a simple fuzzer to see if the decompressor panics. diff --git a/src/internal/zstd/zstd.go b/src/internal/zstd/zstd.go index 0230076f507..0370f601cbf 100644 --- a/src/internal/zstd/zstd.go +++ b/src/internal/zstd/zstd.go @@ -237,7 +237,7 @@ retry: // Figure out the maximum amount of data we need to retain // for backreferences. - var windowSize int + var windowSize uint64 if !singleSegment { // Window descriptor. RFC 3.1.1.1.2. windowDescriptor := r.scratch[0] @@ -246,7 +246,7 @@ retry: windowLog := exponent + 10 windowBase := uint64(1) << windowLog windowAdd := (windowBase / 8) * mantissa - windowSize = int(windowBase + windowAdd) + windowSize = windowBase + windowAdd // Default zstd sets limits on the window size. if fuzzing && (windowLog > 31 || windowSize > 1<<27) { @@ -288,12 +288,13 @@ retry: // When Single_Segment_Flag is set, Window_Descriptor is not present. // In this case, Window_Size is Frame_Content_Size. if singleSegment { - windowSize = int(r.remainingFrameSize) + windowSize = r.remainingFrameSize } // RFC 8878 3.1.1.1.1.2. permits us to set an 8M max on window size. - if windowSize > 8<<20 { - windowSize = 8 << 20 + const maxWindowSize = 8 << 20 + if windowSize > maxWindowSize { + windowSize = maxWindowSize } relativeOffset += headerSize @@ -307,7 +308,7 @@ retry: r.repeatedOffset2 = 4 r.repeatedOffset3 = 8 r.huffmanTableBits = 0 - r.window.reset(windowSize) + r.window.reset(int(windowSize)) r.seqTables[0] = nil r.seqTables[1] = nil r.seqTables[2] = nil