Skip to content

Commit 4a31087

Browse files
AlexanderYastrebovgopherbot
authored andcommitted
internal/zstd: configure window size for single segment frames
Set window size to frame content size when single segment flag is set. For #62513 Change-Id: I2a60c33123aca4f6a631e6d625f4582ff31a63cb GitHub-Last-Rev: 9bafe01 GitHub-Pull-Request: #63224 Reviewed-on: https://go-review.googlesource.com/c/go/+/531075 Auto-Submit: Ian Lance Taylor <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Bryan Mills <[email protected]>
1 parent 48042aa commit 4a31087

File tree

4 files changed

+58
-9
lines changed

4 files changed

+58
-9
lines changed
Binary file not shown.

src/internal/zstd/testdata/README

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
This directory holds files for testing zstd.NewReader.
2+
3+
Each one is a Zstandard compressed file named as hash.arbitrary-name.zst,
4+
where hash is the first eight hexadecimal digits of the SHA256 hash
5+
of the expected uncompressed content:
6+
7+
zstd -d < 1890a371.gettysburg.txt-100x.zst | sha256sum | head -c 8
8+
1890a371
9+
10+
The test uses hash value to verify decompression result.

src/internal/zstd/zstd.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,7 @@ retry:
235235
// Figure out the maximum amount of data we need to retain
236236
// for backreferences.
237237
var windowSize int
238-
if singleSegment {
239-
// No window required, as all the data is in a single buffer.
240-
windowSize = 0
241-
} else {
238+
if !singleSegment {
242239
// Window descriptor. RFC 3.1.1.1.2.
243240
windowDescriptor := r.scratch[0]
244241
exponent := uint64(windowDescriptor >> 3)
@@ -252,11 +249,6 @@ retry:
252249
if fuzzing && (windowLog > 31 || windowSize > 1<<27) {
253250
return r.makeError(relativeOffset, "windowSize too large")
254251
}
255-
256-
// RFC 8878 permits us to set an 8M max on window size.
257-
if windowSize > 8<<20 {
258-
windowSize = 8 << 20
259-
}
260252
}
261253

262254
// Frame_Content_Size. RFC 3.1.1.4.
@@ -278,6 +270,18 @@ retry:
278270
panic("unreachable")
279271
}
280272

273+
// RFC 3.1.1.1.2.
274+
// When Single_Segment_Flag is set, Window_Descriptor is not present.
275+
// In this case, Window_Size is Frame_Content_Size.
276+
if singleSegment {
277+
windowSize = int(r.remainingFrameSize)
278+
}
279+
280+
// RFC 8878 3.1.1.1.1.2. permits us to set an 8M max on window size.
281+
if windowSize > 8<<20 {
282+
windowSize = 8 << 20
283+
}
284+
281285
relativeOffset += headerSize
282286

283287
r.sawFrameHeader = true

src/internal/zstd/zstd_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ package zstd
66

77
import (
88
"bytes"
9+
"crypto/sha256"
910
"fmt"
1011
"internal/race"
1112
"internal/testenv"
1213
"io"
1314
"os"
1415
"os/exec"
16+
"path/filepath"
1517
"strings"
1618
"sync"
1719
"testing"
@@ -237,6 +239,39 @@ func TestAlloc(t *testing.T) {
237239
}
238240
}
239241

242+
func TestFileSamples(t *testing.T) {
243+
samples, err := os.ReadDir("testdata")
244+
if err != nil {
245+
t.Fatal(err)
246+
}
247+
248+
for _, sample := range samples {
249+
name := sample.Name()
250+
if !strings.HasSuffix(name, ".zst") {
251+
continue
252+
}
253+
254+
t.Run(name, func(t *testing.T) {
255+
f, err := os.Open(filepath.Join("testdata", name))
256+
if err != nil {
257+
t.Fatal(err)
258+
}
259+
260+
r := NewReader(f)
261+
h := sha256.New()
262+
if _, err := io.Copy(h, r); err != nil {
263+
t.Fatal(err)
264+
}
265+
got := fmt.Sprintf("%x", h.Sum(nil))[:8]
266+
267+
want, _, _ := strings.Cut(name, ".")
268+
if got != want {
269+
t.Errorf("Wrong uncompressed content hash: got %s, want %s", got, want)
270+
}
271+
})
272+
}
273+
}
274+
240275
func BenchmarkLarge(b *testing.B) {
241276
b.StopTimer()
242277
b.ReportAllocs()

0 commit comments

Comments
 (0)