long matches support overflow

This commit is contained in:
Yann Collet
2016-11-29 13:12:24 -08:00
parent 52e136ed3d
commit 4f5350f610
3 changed files with 12 additions and 10 deletions
+8 -6
View File
@@ -793,8 +793,8 @@ typedef struct {
FSE_DState_t stateOffb; FSE_DState_t stateOffb;
FSE_DState_t stateML; FSE_DState_t stateML;
size_t prevOffset[ZSTD_REP_NUM]; size_t prevOffset[ZSTD_REP_NUM];
const BYTE* ptr;
const BYTE* base; const BYTE* base;
size_t pos;
iPtrDiff gotoDict; iPtrDiff gotoDict;
} seqState_t; } seqState_t;
@@ -864,15 +864,17 @@ static seq_t ZSTD_decodeSequenceLong(seqState_t* seqState)
if (MEM_32bits() || if (MEM_32bits() ||
(totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BIT_reloadDStream(&seqState->DStream); (totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BIT_reloadDStream(&seqState->DStream);
seq.match = seqState->ptr + seq.litLength - seq.offset; /* single memory segment ! */ { size_t const pos = seqState->pos + seq.litLength;
if (seq.match < seqState->base) seq.match += seqState->gotoDict; /* what if seq.match underflows ? prefetch is a non issue, but match has now a wrong address */ seq.match = seqState->base + pos - seq.offset; /* single memory segment */
if (seq.offset > pos) seq.match += seqState->gotoDict; /* separate memory segment */
seqState->pos = pos + seq.matchLength;
}
/* ANS state update */ /* ANS state update */
FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */ FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */ FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */ FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
seqState->ptr += seq.matchLength + seq.litLength;
return seq; return seq;
} }
@@ -1042,8 +1044,8 @@ static size_t ZSTD_decompressSequencesLong(
int seqNb; int seqNb;
dctx->fseEntropy = 1; dctx->fseEntropy = 1;
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->rep[i]; } { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->rep[i]; }
seqState.ptr = op;
seqState.base = base; seqState.base = base;
seqState.pos = (size_t)(op-base);
seqState.gotoDict = (iPtrDiff)(dictEnd - base); seqState.gotoDict = (iPtrDiff)(dictEnd - base);
CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected); CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend-ip), corruption_detected);
FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr); FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
@@ -1194,7 +1196,7 @@ size_t ZSTD_execSequence(BYTE* op,
if (sequence.offset > (size_t)(oLitEnd - base)) { if (sequence.offset > (size_t)(oLitEnd - base)) {
/* offset beyond prefix */ /* offset beyond prefix */
if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected); if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);
match = dictEnd - (base-match); match += (dictEnd-base);
if (match + sequence.matchLength <= dictEnd) { if (match + sequence.matchLength <= dictEnd) {
memmove(oLitEnd, match, sequence.matchLength); memmove(oLitEnd, match, sequence.matchLength);
return sequenceLength; return sequenceLength;
+3 -3
View File
@@ -175,7 +175,7 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
{ U64 fastestC = (U64)(-1LL), fastestD = (U64)(-1LL); { U64 fastestC = (U64)(-1LL), fastestD = (U64)(-1LL);
U64 const crcOrig = XXH64(srcBuffer, srcSize, 0); U64 const crcOrig = XXH64(srcBuffer, srcSize, 0);
UTIL_time_t coolTime; UTIL_time_t coolTime;
U64 const maxTime = (g_nbSeconds * TIMELOOP_MICROSEC) + 100; U64 const maxTime = (g_nbSeconds * TIMELOOP_MICROSEC) + 1;
U64 totalCTime=0, totalDTime=0; U64 totalCTime=0, totalDTime=0;
U32 cCompleted=0, dCompleted=0; U32 cCompleted=0, dCompleted=0;
# define NB_MARKS 4 # define NB_MARKS 4
@@ -234,7 +234,7 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
{ U64 const clockSpan = UTIL_clockSpanMicro(clockStart, ticksPerSecond); { U64 const clockSpan = UTIL_clockSpanMicro(clockStart, ticksPerSecond);
if (clockSpan < fastestC*nbLoops) fastestC = clockSpan / nbLoops; if (clockSpan < fastestC*nbLoops) fastestC = clockSpan / nbLoops;
totalCTime += clockSpan; totalCTime += clockSpan;
cCompleted = totalCTime>maxTime; cCompleted = (totalCTime >= maxTime);
} } } }
cSize = 0; cSize = 0;
@@ -279,7 +279,7 @@ static int BMK_benchMem(const void* srcBuffer, size_t srcSize,
{ U64 const clockSpan = UTIL_clockSpanMicro(clockStart, ticksPerSecond); { U64 const clockSpan = UTIL_clockSpanMicro(clockStart, ticksPerSecond);
if (clockSpan < fastestD*nbLoops) fastestD = clockSpan / nbLoops; if (clockSpan < fastestD*nbLoops) fastestD = clockSpan / nbLoops;
totalDTime += clockSpan; totalDTime += clockSpan;
dCompleted = totalDTime>maxTime; dCompleted = (totalDTime >= maxTime);
} } } }
markNb = (markNb+1) % NB_MARKS; markNb = (markNb+1) % NB_MARKS;
+1 -1
View File
@@ -16,7 +16,7 @@ roundTripTest() {
rm -f tmp1 tmp2 rm -f tmp1 tmp2
$ECHO "roundTripTest: ./datagen $1 $p | $ZSTD -v$c | $ZSTD -d" $ECHO "roundTripTest: ./datagen $1 $p | $ZSTD -v$c | $ZSTD -d"
./datagen $1 $p | $MD5SUM > tmp1 ./datagen $1 $p | $MD5SUM > tmp1
./datagen $1 $p | $ZSTD -v$c | $ZSTD -d | $MD5SUM > tmp2 ./datagen $1 $p | $ZSTD --ultra -v$c | $ZSTD -d | $MD5SUM > tmp2
diff -q tmp1 tmp2 diff -q tmp1 tmp2
} }