Skip to content

Commit 4469f54

Browse files
committed
compress/flate: fix another deflate Reset inconsistency
While investigating #34121, fixed by CL 193605, I discovered another case where Reset was not quite resetting enough. This specific case is not a problem in Reset itself but rather that the Huffman bit writer in one code path is using uninitialized memory left over from a previous block, making the compression not choose the optimal compression method. Fixes #34121. Change-Id: I29245b28214d924e382f91e2c56b4b8a9b7da13d Reviewed-on: https://go-review.googlesource.com/c/go/+/243140 Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
1 parent 8d43307 commit 4469f54

File tree

2 files changed

+41
-16
lines changed

2 files changed

+41
-16
lines changed

src/compress/flate/deflate_test.go

+40-16
Original file line numberDiff line numberDiff line change
@@ -512,33 +512,57 @@ func TestWriterReset(t *testing.T) {
512512
t.Errorf("level %d Writer not reset after Reset", level)
513513
}
514514
}
515-
testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, NoCompression) })
516-
testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, DefaultCompression) })
517-
testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriter(w, BestCompression) })
518-
dict := []byte("we are the world")
519-
testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, NoCompression, dict) })
520-
testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, DefaultCompression, dict) })
521-
testResetOutput(t, func(w io.Writer) (*Writer, error) { return NewWriterDict(w, BestCompression, dict) })
515+
516+
levels := []int{0, 1, 2, 5, 9}
517+
for _, level := range levels {
518+
t.Run(fmt.Sprint(level), func(t *testing.T) {
519+
testResetOutput(t, level, nil)
520+
})
521+
}
522+
523+
t.Run("dict", func(t *testing.T) {
524+
for _, level := range levels {
525+
t.Run(fmt.Sprint(level), func(t *testing.T) {
526+
testResetOutput(t, level, nil)
527+
})
528+
}
529+
})
522530
}
523531

524-
func testResetOutput(t *testing.T, newWriter func(w io.Writer) (*Writer, error)) {
532+
func testResetOutput(t *testing.T, level int, dict []byte) {
533+
writeData := func(w *Writer) {
534+
msg := []byte("now is the time for all good gophers")
535+
w.Write(msg)
536+
w.Flush()
537+
538+
hello := []byte("hello world")
539+
for i := 0; i < 1024; i++ {
540+
w.Write(hello)
541+
}
542+
543+
fill := bytes.Repeat([]byte("x"), 65000)
544+
w.Write(fill)
545+
}
546+
525547
buf := new(bytes.Buffer)
526-
w, err := newWriter(buf)
548+
var w *Writer
549+
var err error
550+
if dict == nil {
551+
w, err = NewWriter(buf, level)
552+
} else {
553+
w, err = NewWriterDict(buf, level, dict)
554+
}
527555
if err != nil {
528556
t.Fatalf("NewWriter: %v", err)
529557
}
530-
b := []byte("hello world")
531-
for i := 0; i < 1024; i++ {
532-
w.Write(b)
533-
}
558+
559+
writeData(w)
534560
w.Close()
535561
out1 := buf.Bytes()
536562

537563
buf2 := new(bytes.Buffer)
538564
w.Reset(buf2)
539-
for i := 0; i < 1024; i++ {
540-
w.Write(b)
541-
}
565+
writeData(w)
542566
w.Close()
543567
out2 := buf2.Bytes()
544568

src/compress/flate/huffman_bit_writer.go

+1
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,7 @@ func (w *huffmanBitWriter) writeBlockHuff(eof bool, input []byte) {
634634
w.literalFreq[endBlockMarker] = 1
635635

636636
const numLiterals = endBlockMarker + 1
637+
w.offsetFreq[0] = 1
637638
const numOffsets = 1
638639

639640
w.literalEncoding.generate(w.literalFreq, 15)

0 commit comments

Comments
 (0)