diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index a1bf866c6..c21a8c982 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -2497,12 +2497,14 @@ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc) ZSTD_Sequence* outSeqs = &zc->seqCollector.seqStart[zc->seqCollector.seqIndex]; size_t i; - int repIdx; + repcodes_t updatedRepcodes; assert(zc->seqCollector.seqIndex + 1 < zc->seqCollector.maxSequences); /* Ensure we have enough space for last literals "sequence" */ assert(zc->seqCollector.maxSequences >= seqStoreSeqSize + 1); + ZSTD_memcpy(updatedRepcodes.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t)); for (i = 0; i < seqStoreSeqSize; ++i) { + U32 rawOffset = seqStoreSeqs[i].offset - ZSTD_REP_NUM; outSeqs[i].litLength = seqStoreSeqs[i].litLength; outSeqs[i].matchLength = seqStoreSeqs[i].matchLength + MINMATCH; outSeqs[i].rep = 0; @@ -2516,27 +2518,26 @@ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc) } if (seqStoreSeqs[i].offset <= ZSTD_REP_NUM) { + /* Derive the correct offset corresponding to a repcode */ outSeqs[i].rep = seqStoreSeqs[i].offset; - repIdx = (unsigned int)i - seqStoreSeqs[i].offset; - - if (seqStoreSeqs[i].litLength == 0) { - if (seqStoreSeqs[i].offset < 3) { - --repIdx; + if (outSeqs[i].litLength != 0) { + rawOffset = updatedRepcodes.rep[outSeqs[i].rep - 1]; + } else { + if (outSeqs[i].rep == 3) { + rawOffset = updatedRepcodes.rep[0] - 1; } else { - repIdx = (unsigned int)i - 1; + rawOffset = updatedRepcodes.rep[outSeqs[i].rep]; } } - assert(repIdx >= -3); - outSeqs[i].offset = repIdx >= 0 ? outSeqs[repIdx].offset : repStartValue[-repIdx - 1]; - if (outSeqs[i].rep == 3 && outSeqs[i].litLength == 0) { - --outSeqs[i].offset; - } - } else { - outSeqs[i].offset = seqStoreSeqs[i].offset - ZSTD_REP_NUM; } + outSeqs[i].offset = rawOffset; + /* seqStoreSeqs[i].offset == offCode+1, and ZSTD_updateRep() expects offCode + so we provide seqStoreSeqs[i].offset - 1 */ + updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, + seqStoreSeqs[i].offset - 1, + seqStoreSeqs[i].litLength == 0); literalsRead += outSeqs[i].litLength; } - /* Insert last literals (if any exist) in the block as a sequence with ml == off == 0. * If there are no last literals, then we'll emit (of: 0, ml: 0, ll: 0), which is a marker * for the block boundary, according to the API. @@ -2546,7 +2547,6 @@ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc) outSeqs[i].litLength = (U32)lastLLSize; outSeqs[i].matchLength = outSeqs[i].offset = outSeqs[i].rep = 0; seqStoreSeqSize++; - zc->seqCollector.seqIndex += seqStoreSeqSize; } diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 65e442093..2afd10935 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -2721,9 +2721,9 @@ static int basicUnitTests(U32 const seed, double compressibility) if (seqs == NULL) goto _output_error; assert(cctx != NULL); - + ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, 19); /* Populate src with random data */ - RDG_genBuffer(CNBuffer, srcSize, compressibility, 0., seed); + RDG_genBuffer(CNBuffer, srcSize, compressibility, 0.5, seed); /* Test with block delimiters roundtrip */ seqsSize = ZSTD_generateSequences(cctx, seqs, srcSize, src, srcSize);