diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index c51fd1853ff..159ff561c86 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -8051,6 +8051,7 @@ ZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx, FORWARD_IF_ERROR(block.nbSequences, "Error while trying to determine nb of sequences for a block"); assert(block.nbSequences <= nbSequences); RETURN_ERROR_IF(block.litSize > litSize, externalSequences_invalid, "discrepancy: Sequences require more literals than present in buffer"); + RETURN_ERROR_IF(block.blockSize > cctx->blockSizeMax, externalSequences_invalid, "sequences incorrectly define a too large block"); ZSTD_resetSeqStore(&cctx->seqStore); conversionStatus = ZSTD_convertBlockSequences(cctx, diff --git a/lib/zstd.h b/lib/zstd.h index e0862eb3fa8..ef5160084aa 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1701,6 +1701,8 @@ ZSTD_compressSequences(ZSTD_CCtx* cctx, * - @litBufCapacity is the size of the underlying buffer into which literals are written, starting at address @literals. * @litBufCapacity must be at least 8 bytes larger than @litSize. * - @decompressedSize must be correct, and correspond to the sum of all Sequences. Any discrepancy will generate an error. + * - Each block must regenerate at most ZSTD_BLOCKSIZE_MAX bytes, or less with a smaller window or ZSTD_c_maxBlockSize. + * A larger block will generate an error. * @return : final compressed size, or a ZSTD error code. */ ZSTDLIB_STATIC_API size_t diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 4a2f0bac8f8..dda4b071b35 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -4832,6 +4832,18 @@ static int basicUnitTests(U32 const seed, double compressibility) } DISPLAYLEVEL(3, "OK \n"); + DISPLAYLEVEL(3, "test%3i : ZSTD_compressSequencesAndLiterals : reject a too large block : ", testNb++); + { /* one block of ZSTD_BLOCKSIZE_MAX + 1 bytes : 16 literals and a match, then the block delimiter */ + ZSTD_Sequence const seqs[2] = { { 1, 16, ZSTD_BLOCKSIZE_MAX + 1 - 16, 0 }, { 0, 0, 0, 0 } }; + ZSTD_CCtx* const cctx = ZSTD_createCCtx(); + CHECK(cctx != NULL); + CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_blockDelimiters, ZSTD_sf_explicitBlockDelimiters) ); + CHECK( ZSTD_isError(ZSTD_compressSequencesAndLiterals(cctx, compressedBuffer, compressedBufferSize, + seqs, 2, CNBuffer, 16, CNBuffSize, ZSTD_BLOCKSIZE_MAX + 1)) ); + ZSTD_freeCCtx(cctx); + } + DISPLAYLEVEL(3, "OK \n"); + /* Multiple blocks of zeros test */ #define LONGZEROSLENGTH 1000000 /* 1MB of zeros */ DISPLAYLEVEL(3, "test%3i : compress %u zeroes : ", testNb++, LONGZEROSLENGTH);