]> Cypherpunks repositories - gostls13.git/commitdiff
compress/flate: tighten the BestSpeed max match offset bound.
authorNigel Tao <nigeltao@golang.org>
Sat, 29 Oct 2016 02:23:50 +0000 (13:23 +1100)
committerNigel Tao <nigeltao@golang.org>
Sun, 30 Oct 2016 22:52:14 +0000 (22:52 +0000)
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 <thebrokentoaster@gmail.com>
Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/compress/flate/deflate_test.go
src/compress/flate/deflatefast.go

index 415e97262ff60314ae4ab32f2281fb26930751b6..0f41695bf3492a23d70a3c96d6117ec1c464d858 100644 (file)
@@ -798,3 +798,62 @@ func TestBestSpeedMatch(t *testing.T) {
                }
        }
 }
+
+func TestBestSpeedMaxMatchOffset(t *testing.T) {
+       const abc, xyz = "abcdefgh", "stuvwxyz"
+       for _, matchBefore := range []bool{false, true} {
+               for _, extra := range []int{0, inputMargin - 1, inputMargin, inputMargin + 1, 2 * inputMargin} {
+                       for offsetAdj := -5; offsetAdj <= +5; offsetAdj++ {
+                               report := func(desc string, err error) {
+                                       t.Errorf("matchBefore=%t, extra=%d, offsetAdj=%d: %s%v",
+                                               matchBefore, extra, offsetAdj, desc, err)
+                               }
+
+                               offset := maxMatchOffset + offsetAdj
+
+                               // Make src to be a []byte of the form
+                               //      "%s%s%s%s%s" % (abc, zeros0, xyzMaybe, abc, zeros1)
+                               // where:
+                               //      zeros0 is approximately maxMatchOffset zeros.
+                               //      xyzMaybe is either xyz or the empty string.
+                               //      zeros1 is between 0 and 30 zeros.
+                               // The difference between the two abc's will be offset, which
+                               // is maxMatchOffset plus or minus a small adjustment.
+                               src := make([]byte, offset+len(abc)+extra)
+                               copy(src, abc)
+                               if !matchBefore {
+                                       copy(src[offset-len(xyz):], xyz)
+                               }
+                               copy(src[offset:], abc)
+
+                               buf := new(bytes.Buffer)
+                               w, err := NewWriter(buf, BestSpeed)
+                               if err != nil {
+                                       report("NewWriter: ", err)
+                                       continue
+                               }
+                               if _, err := w.Write(src); err != nil {
+                                       report("Write: ", err)
+                                       continue
+                               }
+                               if err := w.Close(); err != nil {
+                                       report("Writer.Close: ", err)
+                                       continue
+                               }
+
+                               r := NewReader(buf)
+                               dst, err := ioutil.ReadAll(r)
+                               r.Close()
+                               if err != nil {
+                                       report("ReadAll: ", err)
+                                       continue
+                               }
+
+                               if !bytes.Equal(dst, src) {
+                                       report("", fmt.Errorf("bytes differ after round-tripping"))
+                                       continue
+                               }
+                       }
+               }
+       }
+}
index 5201b2ee1ca3a06447dc7bf2c9652ad0f4e15253..a1636a37d67cfa9826e78de10618c94faa12f5d6 100644 (file)
@@ -55,7 +55,7 @@ func newDeflateFast() *deflateFast {
        return &deflateFast{cur: maxStoreBlockSize, prev: make([]byte, 0, maxStoreBlockSize)}
 }
 
-// encode encodes a block given in src and encodes tokens
+// encode encodes a block given in src and appends tokens
 // to dst and returns the result.
 func (e *deflateFast) encode(dst []token, src []byte) []token {
        // Ensure that e.cur doesn't wrap.
@@ -116,8 +116,7 @@ func (e *deflateFast) encode(dst []token, src []byte) []token {
                        nextHash = hash(now)
 
                        offset := s - (candidate.offset - e.cur)
-                       // TODO: >= should be >, and add a test for that.
-                       if offset >= maxMatchOffset || cv != candidate.val {
+                       if offset > maxMatchOffset || cv != candidate.val {
                                // Out of range or not matched.
                                cv = now
                                continue
@@ -171,8 +170,7 @@ func (e *deflateFast) encode(dst []token, src []byte) []token {
                        e.table[currHash&tableMask] = tableEntry{offset: e.cur + s, val: uint32(x)}
 
                        offset := s - (candidate.offset - e.cur)
-                       // TODO: >= should be >, and add a test for that.
-                       if offset >= maxMatchOffset || uint32(x) != candidate.val {
+                       if offset > maxMatchOffset || uint32(x) != candidate.val {
                                cv = uint32(x >> 8)
                                nextHash = hash(cv)
                                s++