]> Cypherpunks repositories - gostls13.git/commitdiff
internal/zstd: allow zero dictionary id
authorAlexander Yastrebov <yastrebov.alex@gmail.com>
Wed, 27 Sep 2023 23:53:37 +0000 (23:53 +0000)
committerGopher Robot <gobot@golang.org>
Thu, 28 Sep 2023 17:56:15 +0000 (17:56 +0000)
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 <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>

src/internal/zstd/testdata/fcf30b99.zero-dictionary-ids.zst [new file with mode: 0644]
src/internal/zstd/zstd.go

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 (file)
index 0000000..1be89e8
Binary files /dev/null and b/src/internal/zstd/testdata/fcf30b99.zero-dictionary-ids.zst differ
index 6b1aac0c5f7593db4ad1a85df4e0630adc648a1f..72d733f6dd4f990ab28c0993923c0144d2a5e2cc 100644 (file)
@@ -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