Skip to content

Commit

Permalink
zstd: Fix incorrect encoding in best mode (#415)
Browse files Browse the repository at this point in the history
Fix incorrect intermediate when testing current value for repeat+3 offsets.

Fixes #414
  • Loading branch information
klauspost committed Aug 12, 2021
1 parent 2ad8e19 commit bf4861f
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 9 deletions.
30 changes: 21 additions & 9 deletions zstd/enc_best.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package zstd

import (
"bytes"
"fmt"

"github.com/klauspost/compress"
Expand Down Expand Up @@ -208,6 +209,11 @@ encodeLoop:
if s-offset >= e.maxMatchOff || load3232(src, offset) != first {
return match{s: s, est: highScore}
}
if debugAsserts {
if !bytes.Equal(src[s:s+4], src[offset:offset+4]) {
panic(fmt.Sprintf("first match mismatch: %v != %v, first: %08x", src[s:s+4], src[offset:offset+4], first))
}
}
m := match{offset: offset, s: s, length: 4 + e.matchlen(s+4, offset+4, src), rep: rep}
m.estBits(bitsPerByte)
return m
Expand All @@ -218,17 +224,17 @@ encodeLoop:
best = bestOf(best, matchAt(candidateS.prev-e.cur, s, uint32(cv), -1))

if canRepeat && best.length < goodEnough {
cv := uint32(cv >> 8)
cv32 := uint32(cv >> 8)
spp := s + 1
best = bestOf(best, matchAt(spp-offset1, spp, cv, 1))
best = bestOf(best, matchAt(spp-offset2, spp, cv, 2))
best = bestOf(best, matchAt(spp-offset3, spp, cv, 3))
best = bestOf(best, matchAt(spp-offset1, spp, cv32, 1))
best = bestOf(best, matchAt(spp-offset2, spp, cv32, 2))
best = bestOf(best, matchAt(spp-offset3, spp, cv32, 3))
if best.length > 0 {
cv >>= 16
cv32 = uint32(cv >> 24)
spp += 2
best = bestOf(best, matchAt(spp-offset1, spp, cv, 1))
best = bestOf(best, matchAt(spp-offset2, spp, cv, 2))
best = bestOf(best, matchAt(spp-offset3, spp, cv, 3))
best = bestOf(best, matchAt(spp-offset1, spp, cv32, 1))
best = bestOf(best, matchAt(spp-offset2, spp, cv32, 2))
best = bestOf(best, matchAt(spp-offset3, spp, cv32, 3))
}
}
// Load next and check...
Expand Down Expand Up @@ -281,6 +287,12 @@ encodeLoop:
}
}

if debugAsserts {
if !bytes.Equal(src[best.s:best.s+best.length], src[best.offset:best.offset+best.length]) {
panic(fmt.Sprintf("match mismatch: %v != %v", src[best.s:best.s+best.length], src[best.offset:best.offset+best.length]))
}
}

// We have a match, we can store the forward value
if best.rep > 0 {
s = best.s
Expand Down Expand Up @@ -356,7 +368,7 @@ encodeLoop:
panic(fmt.Sprintf("s (%d) <= t (%d)", s, t))
}

if debugAsserts && canRepeat && int(offset1) > len(src) {
if debugAsserts && int(offset1) > len(src) {
panic("invalid offset")
}

Expand Down
Binary file modified zstd/testdata/regression.zip
Binary file not shown.

0 comments on commit bf4861f

Please sign in to comment.