|
|
|
@@ -947,13 +947,52 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c
|
|
|
|
|
return seq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
|
|
|
|
static int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd)
|
|
|
|
|
{
|
|
|
|
|
size_t const windowSize = dctx->fParams.windowSize;
|
|
|
|
|
/* No dictionary used. */
|
|
|
|
|
if (dctx->dictContentEndForFuzzing == NULL) return 0;
|
|
|
|
|
/* Dictionary is not our ext-dict. */
|
|
|
|
|
if (dctx->dictEnd != dctx->dictContentEndForFuzzing) return 0;
|
|
|
|
|
/* Dictionary is not within our window size. */
|
|
|
|
|
if ((size_t)(oLitEnd - prefixStart) >= windowSize) return 0;
|
|
|
|
|
/* Dictionary is active. */
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MEM_STATIC void ZSTD_assertValidSequence(
|
|
|
|
|
ZSTD_DCtx const* dctx,
|
|
|
|
|
BYTE const* op, BYTE const* oend,
|
|
|
|
|
seq_t const seq,
|
|
|
|
|
BYTE const* prefixStart, BYTE const* virtualStart)
|
|
|
|
|
{
|
|
|
|
|
size_t const windowSize = dctx->fParams.windowSize;
|
|
|
|
|
size_t const sequenceSize = seq.litLength + seq.matchLength;
|
|
|
|
|
BYTE const* const oLitEnd = op + seq.litLength;
|
|
|
|
|
assert(op <= oend);
|
|
|
|
|
assert((size_t)(oend - op) >= sequenceSize);
|
|
|
|
|
assert(sequenceSize <= ZSTD_BLOCKSIZE_MAX);
|
|
|
|
|
if (ZSTD_dictionaryIsActive(dctx, prefixStart, oLitEnd)) {
|
|
|
|
|
size_t const dictSize = (size_t)(prefixStart - virtualStart);
|
|
|
|
|
/* Offset must be within the dictionary. */
|
|
|
|
|
assert(seq.offset <= (size_t)(oLitEnd - virtualStart));
|
|
|
|
|
assert(seq.offset <= windowSize + dictSize);
|
|
|
|
|
} else {
|
|
|
|
|
/* Offset must be within our window. */
|
|
|
|
|
assert(seq.offset <= windowSize);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
|
|
|
|
|
FORCE_INLINE_TEMPLATE size_t
|
|
|
|
|
DONT_VECTORIZE
|
|
|
|
|
ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
|
|
|
|
|
void* dst, size_t maxDstSize,
|
|
|
|
|
const void* seqStart, size_t seqSize, int nbSeq,
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset)
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset,
|
|
|
|
|
const int frame)
|
|
|
|
|
{
|
|
|
|
|
const BYTE* ip = (const BYTE*)seqStart;
|
|
|
|
|
const BYTE* const iend = ip + seqSize;
|
|
|
|
@@ -966,6 +1005,7 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
|
|
|
|
|
const BYTE* const vBase = (const BYTE*) (dctx->virtualStart);
|
|
|
|
|
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
|
|
|
|
|
DEBUGLOG(5, "ZSTD_decompressSequences_body");
|
|
|
|
|
(void)frame;
|
|
|
|
|
|
|
|
|
|
/* Regen sequences */
|
|
|
|
|
if (nbSeq) {
|
|
|
|
@@ -1030,6 +1070,9 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
|
|
|
|
|
for ( ; ; ) {
|
|
|
|
|
seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_noPrefetch);
|
|
|
|
|
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd);
|
|
|
|
|
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
|
|
|
|
|
if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);
|
|
|
|
|
#endif
|
|
|
|
|
DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
|
|
|
|
|
BIT_reloadDStream(&(seqState.DStream));
|
|
|
|
|
/* gcc and clang both don't like early returns in this loop.
|
|
|
|
@@ -1068,9 +1111,10 @@ static size_t
|
|
|
|
|
ZSTD_decompressSequences_default(ZSTD_DCtx* dctx,
|
|
|
|
|
void* dst, size_t maxDstSize,
|
|
|
|
|
const void* seqStart, size_t seqSize, int nbSeq,
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset)
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset,
|
|
|
|
|
const int frame)
|
|
|
|
|
{
|
|
|
|
|
return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
|
|
|
|
|
return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
|
|
|
|
|
}
|
|
|
|
|
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
|
|
|
|
|
|
|
|
|
@@ -1080,7 +1124,8 @@ ZSTD_decompressSequencesLong_body(
|
|
|
|
|
ZSTD_DCtx* dctx,
|
|
|
|
|
void* dst, size_t maxDstSize,
|
|
|
|
|
const void* seqStart, size_t seqSize, int nbSeq,
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset)
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset,
|
|
|
|
|
const int frame)
|
|
|
|
|
{
|
|
|
|
|
const BYTE* ip = (const BYTE*)seqStart;
|
|
|
|
|
const BYTE* const iend = ip + seqSize;
|
|
|
|
@@ -1092,6 +1137,7 @@ ZSTD_decompressSequencesLong_body(
|
|
|
|
|
const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart);
|
|
|
|
|
const BYTE* const dictStart = (const BYTE*) (dctx->virtualStart);
|
|
|
|
|
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
|
|
|
|
|
(void)frame;
|
|
|
|
|
|
|
|
|
|
/* Regen sequences */
|
|
|
|
|
if (nbSeq) {
|
|
|
|
@@ -1127,6 +1173,9 @@ ZSTD_decompressSequencesLong_body(
|
|
|
|
|
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
|
|
|
|
|
seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_prefetch);
|
|
|
|
|
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
|
|
|
|
|
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
|
|
|
|
|
if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);
|
|
|
|
|
#endif
|
|
|
|
|
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
|
|
|
|
PREFETCH_L1(sequence.match); PREFETCH_L1(sequence.match + sequence.matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
|
|
|
|
|
sequences[seqNb & STORED_SEQS_MASK] = sequence;
|
|
|
|
@@ -1138,6 +1187,9 @@ ZSTD_decompressSequencesLong_body(
|
|
|
|
|
seqNb -= seqAdvance;
|
|
|
|
|
for ( ; seqNb<nbSeq ; seqNb++) {
|
|
|
|
|
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[seqNb&STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
|
|
|
|
|
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
|
|
|
|
|
if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[seqNb&STORED_SEQS_MASK], prefixStart, dictStart);
|
|
|
|
|
#endif
|
|
|
|
|
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
|
|
|
|
op += oneSeqSize;
|
|
|
|
|
}
|
|
|
|
@@ -1162,9 +1214,10 @@ static size_t
|
|
|
|
|
ZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx,
|
|
|
|
|
void* dst, size_t maxDstSize,
|
|
|
|
|
const void* seqStart, size_t seqSize, int nbSeq,
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset)
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset,
|
|
|
|
|
const int frame)
|
|
|
|
|
{
|
|
|
|
|
return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
|
|
|
|
|
return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
|
|
|
|
|
}
|
|
|
|
|
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */
|
|
|
|
|
|
|
|
|
@@ -1178,9 +1231,10 @@ DONT_VECTORIZE
|
|
|
|
|
ZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx,
|
|
|
|
|
void* dst, size_t maxDstSize,
|
|
|
|
|
const void* seqStart, size_t seqSize, int nbSeq,
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset)
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset,
|
|
|
|
|
const int frame)
|
|
|
|
|
{
|
|
|
|
|
return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
|
|
|
|
|
return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
|
|
|
|
|
}
|
|
|
|
|
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
|
|
|
|
|
|
|
|
|
@@ -1189,9 +1243,10 @@ static TARGET_ATTRIBUTE("bmi2") size_t
|
|
|
|
|
ZSTD_decompressSequencesLong_bmi2(ZSTD_DCtx* dctx,
|
|
|
|
|
void* dst, size_t maxDstSize,
|
|
|
|
|
const void* seqStart, size_t seqSize, int nbSeq,
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset)
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset,
|
|
|
|
|
const int frame)
|
|
|
|
|
{
|
|
|
|
|
return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
|
|
|
|
|
return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
|
|
|
|
|
}
|
|
|
|
|
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */
|
|
|
|
|
|
|
|
|
@@ -1201,21 +1256,23 @@ typedef size_t (*ZSTD_decompressSequences_t)(
|
|
|
|
|
ZSTD_DCtx* dctx,
|
|
|
|
|
void* dst, size_t maxDstSize,
|
|
|
|
|
const void* seqStart, size_t seqSize, int nbSeq,
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset);
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset,
|
|
|
|
|
const int frame);
|
|
|
|
|
|
|
|
|
|
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
|
|
|
|
|
static size_t
|
|
|
|
|
ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,
|
|
|
|
|
const void* seqStart, size_t seqSize, int nbSeq,
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset)
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset,
|
|
|
|
|
const int frame)
|
|
|
|
|
{
|
|
|
|
|
DEBUGLOG(5, "ZSTD_decompressSequences");
|
|
|
|
|
#if DYNAMIC_BMI2
|
|
|
|
|
if (dctx->bmi2) {
|
|
|
|
|
return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
|
|
|
|
|
return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
|
|
|
|
|
return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
|
|
|
|
|
}
|
|
|
|
|
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
|
|
|
|
|
|
|
|
|
@@ -1230,15 +1287,16 @@ static size_t
|
|
|
|
|
ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,
|
|
|
|
|
void* dst, size_t maxDstSize,
|
|
|
|
|
const void* seqStart, size_t seqSize, int nbSeq,
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset)
|
|
|
|
|
const ZSTD_longOffset_e isLongOffset,
|
|
|
|
|
const int frame)
|
|
|
|
|
{
|
|
|
|
|
DEBUGLOG(5, "ZSTD_decompressSequencesLong");
|
|
|
|
|
#if DYNAMIC_BMI2
|
|
|
|
|
if (dctx->bmi2) {
|
|
|
|
|
return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
|
|
|
|
|
return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);
|
|
|
|
|
return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
|
|
|
|
|
}
|
|
|
|
|
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */
|
|
|
|
|
|
|
|
|
@@ -1333,12 +1391,12 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
|
|
|
|
if (usePrefetchDecoder)
|
|
|
|
|
#endif
|
|
|
|
|
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
|
|
|
|
|
return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);
|
|
|
|
|
return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
|
|
|
|
|
/* else */
|
|
|
|
|
return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);
|
|
|
|
|
return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|