From 8eb6542f08f086fb92796f6d8a4531d754947309 Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Sun, 22 Oct 2023 08:44:49 -0700 Subject: [PATCH] zstd: Fix corrupted output in "best" (#876) * zstd: Fix corrupted output in "best" Regression from #784 and followup #793 Fixes #875 A 0 offset backreference was possible when "improve" was successful twice in a row in the "skipBeginning" part, only finding 2 (previously unmatches) length 4 matches, but where start offset decreased by 2 in both cases. This would result in output where the end offset would equal to the next 's', thereby doing a self-reference. Add a general check in "improve" and just reject these. Will also guard against similar issues in the future. This also hints at some potentially suboptimal hash indexing - but I will take that improvement separately. Fuzz test set updated. --- zstd/enc_best.go | 11 ++++++----- zstd/testdata/fuzz/encode-corpus-raw.zip | Bin 1631824 -> 1650597 bytes 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/zstd/enc_best.go b/zstd/enc_best.go index 9819d41453..858f8f43a5 100644 --- a/zstd/enc_best.go +++ b/zstd/enc_best.go @@ -197,12 +197,13 @@ encodeLoop: // Set m to a match at offset if it looks like that will improve compression. improve := func(m *match, offset int32, s int32, first uint32, rep int32) { - if s-offset >= e.maxMatchOff || load3232(src, offset) != first { + delta := s - offset + if delta >= e.maxMatchOff || delta <= 0 || load3232(src, offset) != first { return } if debugAsserts { - if offset <= 0 { - panic(offset) + if offset >= s { + panic(fmt.Sprintf("offset: %d - s:%d - rep: %d - cur :%d - max: %d", offset, s, rep, e.cur, e.maxMatchOff)) } 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)) @@ -343,8 +344,8 @@ encodeLoop: if best.rep > 0 { var seq seq seq.matchLen = uint32(best.length - zstdMinMatch) - if debugAsserts && s <= nextEmit { - panic("s <= nextEmit") + if debugAsserts && s < nextEmit { + panic("s < nextEmit") } addLiterals(&seq, best.s) diff --git a/zstd/testdata/fuzz/encode-corpus-raw.zip b/zstd/testdata/fuzz/encode-corpus-raw.zip index 4b34bcfe8c6bc14836699e5de3422f2205f075f5..7f44026c646738aab3970c521835e98b39a3d1d9 100644 GIT binary patch delta 18883 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 delta 88 zcmZ2_Kjp%iF7M2#)7Pc1l7LFFq7OocV7M>Q~7QPn#7J(MQ7NHj57LgXw oEn@HV+KtP_fLMIHak+%wb`e%K1|U%8Q0DO4&cyIWPYlQd04drT!T