Skip to content

Commit 590fce4

Browse files
committed
compress/flate: tighten the BestSpeed max match offset bound.
Previously, we were off by one. Also fix a comment typo. Change-Id: Ib94d23acc56d5fccd44144f71655481f98803ac8 Reviewed-on: https://go-review.googlesource.com/32149 Reviewed-by: Joe Tsai <[email protected]> Run-TryBot: Joe Tsai <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent f135106 commit 590fce4

File tree

2 files changed

+62
-5
lines changed

2 files changed

+62
-5
lines changed

src/compress/flate/deflate_test.go

+59
Original file line numberDiff line numberDiff line change
@@ -798,3 +798,62 @@ func TestBestSpeedMatch(t *testing.T) {
798798
}
799799
}
800800
}
801+
802+
func TestBestSpeedMaxMatchOffset(t *testing.T) {
803+
const abc, xyz = "abcdefgh", "stuvwxyz"
804+
for _, matchBefore := range []bool{false, true} {
805+
for _, extra := range []int{0, inputMargin - 1, inputMargin, inputMargin + 1, 2 * inputMargin} {
806+
for offsetAdj := -5; offsetAdj <= +5; offsetAdj++ {
807+
report := func(desc string, err error) {
808+
t.Errorf("matchBefore=%t, extra=%d, offsetAdj=%d: %s%v",
809+
matchBefore, extra, offsetAdj, desc, err)
810+
}
811+
812+
offset := maxMatchOffset + offsetAdj
813+
814+
// Make src to be a []byte of the form
815+
// "%s%s%s%s%s" % (abc, zeros0, xyzMaybe, abc, zeros1)
816+
// where:
817+
// zeros0 is approximately maxMatchOffset zeros.
818+
// xyzMaybe is either xyz or the empty string.
819+
// zeros1 is between 0 and 30 zeros.
820+
// The difference between the two abc's will be offset, which
821+
// is maxMatchOffset plus or minus a small adjustment.
822+
src := make([]byte, offset+len(abc)+extra)
823+
copy(src, abc)
824+
if !matchBefore {
825+
copy(src[offset-len(xyz):], xyz)
826+
}
827+
copy(src[offset:], abc)
828+
829+
buf := new(bytes.Buffer)
830+
w, err := NewWriter(buf, BestSpeed)
831+
if err != nil {
832+
report("NewWriter: ", err)
833+
continue
834+
}
835+
if _, err := w.Write(src); err != nil {
836+
report("Write: ", err)
837+
continue
838+
}
839+
if err := w.Close(); err != nil {
840+
report("Writer.Close: ", err)
841+
continue
842+
}
843+
844+
r := NewReader(buf)
845+
dst, err := ioutil.ReadAll(r)
846+
r.Close()
847+
if err != nil {
848+
report("ReadAll: ", err)
849+
continue
850+
}
851+
852+
if !bytes.Equal(dst, src) {
853+
report("", fmt.Errorf("bytes differ after round-tripping"))
854+
continue
855+
}
856+
}
857+
}
858+
}
859+
}

src/compress/flate/deflatefast.go

+3-5
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func newDeflateFast() *deflateFast {
5555
return &deflateFast{cur: maxStoreBlockSize, prev: make([]byte, 0, maxStoreBlockSize)}
5656
}
5757

58-
// encode encodes a block given in src and encodes tokens
58+
// encode encodes a block given in src and appends tokens
5959
// to dst and returns the result.
6060
func (e *deflateFast) encode(dst []token, src []byte) []token {
6161
// Ensure that e.cur doesn't wrap.
@@ -116,8 +116,7 @@ func (e *deflateFast) encode(dst []token, src []byte) []token {
116116
nextHash = hash(now)
117117

118118
offset := s - (candidate.offset - e.cur)
119-
// TODO: >= should be >, and add a test for that.
120-
if offset >= maxMatchOffset || cv != candidate.val {
119+
if offset > maxMatchOffset || cv != candidate.val {
121120
// Out of range or not matched.
122121
cv = now
123122
continue
@@ -171,8 +170,7 @@ func (e *deflateFast) encode(dst []token, src []byte) []token {
171170
e.table[currHash&tableMask] = tableEntry{offset: e.cur + s, val: uint32(x)}
172171

173172
offset := s - (candidate.offset - e.cur)
174-
// TODO: >= should be >, and add a test for that.
175-
if offset >= maxMatchOffset || uint32(x) != candidate.val {
173+
if offset > maxMatchOffset || uint32(x) != candidate.val {
176174
cv = uint32(x >> 8)
177175
nextHash = hash(cv)
178176
s++

0 commit comments

Comments
 (0)