From a57658171fb6db2d3c3681d6173ffa59ab94fc65 Mon Sep 17 00:00:00 2001 From: Alexander Yastrebov Date: Wed, 27 Sep 2023 23:53:37 +0000 Subject: [PATCH] internal/zstd: allow zero dictionary id A value of 0 has same meaning as no Dictionary_ID, in which case the frame may or may not need a dictionary to be decoded, and the ID of such a dictionary is not specified. See https://github.com/facebook/zstd/issues/2172 For #62513 Change-Id: If0eafcbc5d2188576f0cb687234e30c9eb4037a6 GitHub-Last-Rev: 9cf12dcf194a90367a74b808bbe464815f71f42a GitHub-Pull-Request: golang/go#63268 Reviewed-on: https://go-review.googlesource.com/c/go/+/531515 LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Reviewed-by: Than McIntosh Auto-Submit: Ian Lance Taylor --- .../testdata/fcf30b99.zero-dictionary-ids.zst | Bin 0 -> 64 bytes src/internal/zstd/zstd.go | 23 ++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 src/internal/zstd/testdata/fcf30b99.zero-dictionary-ids.zst diff --git a/src/internal/zstd/testdata/fcf30b99.zero-dictionary-ids.zst b/src/internal/zstd/testdata/fcf30b99.zero-dictionary-ids.zst new file mode 100644 index 0000000000000000000000000000000000000000..1be89e812ef9737f18232f4956f9cd8ff9640e12 GIT binary patch literal 64 ocmdPcs{fZYfWeS~AtN;>C!Z_0WA8)_pcq>K1EwH5P!LTR0GXc@h5!Hn literal 0 HcmV?d00001 diff --git a/src/internal/zstd/zstd.go b/src/internal/zstd/zstd.go index 6b1aac0c5f..72d733f6dd 100644 --- a/src/internal/zstd/zstd.go +++ b/src/internal/zstd/zstd.go @@ -221,13 +221,15 @@ retry: r.checksum.reset() } - if descriptor&3 != 0 { - return r.makeError(relativeOffset, "dictionaries are not supported") + // Dictionary_ID_Flag. RFC 3.1.1.1.1.6. + dictionaryIdSize := 0 + if dictIdFlag := descriptor & 3; dictIdFlag != 0 { + dictionaryIdSize = 1 << (dictIdFlag - 1) } relativeOffset++ - headerSize := windowDescriptorSize + fcsFieldSize + headerSize := windowDescriptorSize + dictionaryIdSize + fcsFieldSize if _, err := io.ReadFull(r.r, r.scratch[:headerSize]); err != nil { return r.wrapNonEOFError(relativeOffset, err) @@ -252,10 +254,21 @@ retry: } } - // Frame_Content_Size. RFC 3.1.1.4. + // Dictionary_ID. RFC 3.1.1.1.3. + if dictionaryIdSize != 0 { + dictionaryId := r.scratch[windowDescriptorSize : windowDescriptorSize+dictionaryIdSize] + // Allow only zero Dictionary ID. + for _, b := range dictionaryId { + if b != 0 { + return r.makeError(relativeOffset, "dictionaries are not supported") + } + } + } + + // Frame_Content_Size. RFC 3.1.1.1.4. r.frameSizeUnknown = false r.remainingFrameSize = 0 - fb := r.scratch[windowDescriptorSize:] + fb := r.scratch[windowDescriptorSize+dictionaryIdSize:] switch fcsFieldSize { case 0: r.frameSizeUnknown = true -- 2.50.0