mirror of
https://github.com/facebook/zstd.git
synced 2025-08-05 19:15:58 +03:00
Merge pull request #2278 from senhuang42/ignore_checksum_advanced_param
New advanced decompression param to ignore checksums
This commit is contained in:
@@ -114,6 +114,8 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|||||||
dctx->oversizedDuration = 0;
|
dctx->oversizedDuration = 0;
|
||||||
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
||||||
dctx->outBufferMode = ZSTD_obm_buffered;
|
dctx->outBufferMode = ZSTD_obm_buffered;
|
||||||
|
dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
|
||||||
|
dctx->validateChecksum = 1;
|
||||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||||
dctx->dictContentEndForFuzzing = NULL;
|
dctx->dictContentEndForFuzzing = NULL;
|
||||||
#endif
|
#endif
|
||||||
@@ -446,7 +448,8 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
|
|||||||
RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
|
RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
|
||||||
dictionary_wrong, "");
|
dictionary_wrong, "");
|
||||||
#endif
|
#endif
|
||||||
if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);
|
dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
|
||||||
|
if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,7 +664,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ZSTD_isError(decodedSize)) return decodedSize;
|
if (ZSTD_isError(decodedSize)) return decodedSize;
|
||||||
if (dctx->fParams.checksumFlag)
|
if (dctx->validateChecksum)
|
||||||
XXH64_update(&dctx->xxhState, op, decodedSize);
|
XXH64_update(&dctx->xxhState, op, decodedSize);
|
||||||
if (decodedSize != 0)
|
if (decodedSize != 0)
|
||||||
op += decodedSize;
|
op += decodedSize;
|
||||||
@@ -676,11 +679,13 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
|||||||
corruption_detected, "");
|
corruption_detected, "");
|
||||||
}
|
}
|
||||||
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
|
if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
|
||||||
|
RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
|
||||||
|
if (!dctx->forceIgnoreChecksum) {
|
||||||
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
|
U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);
|
||||||
U32 checkRead;
|
U32 checkRead;
|
||||||
RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
|
|
||||||
checkRead = MEM_readLE32(ip);
|
checkRead = MEM_readLE32(ip);
|
||||||
RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
|
RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
|
||||||
|
}
|
||||||
ip += 4;
|
ip += 4;
|
||||||
remainingSrcSize -= 4;
|
remainingSrcSize -= 4;
|
||||||
}
|
}
|
||||||
@@ -977,7 +982,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|||||||
RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
|
RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
|
||||||
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
|
DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
|
||||||
dctx->decodedSize += rSize;
|
dctx->decodedSize += rSize;
|
||||||
if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);
|
if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);
|
||||||
dctx->previousDstEnd = (char*)dst + rSize;
|
dctx->previousDstEnd = (char*)dst + rSize;
|
||||||
|
|
||||||
/* Stay on the same stage until we are finished streaming the block. */
|
/* Stay on the same stage until we are finished streaming the block. */
|
||||||
@@ -1007,10 +1012,13 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
|||||||
|
|
||||||
case ZSTDds_checkChecksum:
|
case ZSTDds_checkChecksum:
|
||||||
assert(srcSize == 4); /* guaranteed by dctx->expected */
|
assert(srcSize == 4); /* guaranteed by dctx->expected */
|
||||||
{ U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
|
{
|
||||||
|
if (dctx->validateChecksum) {
|
||||||
|
U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);
|
||||||
U32 const check32 = MEM_readLE32(src);
|
U32 const check32 = MEM_readLE32(src);
|
||||||
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
||||||
RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
|
RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
|
||||||
|
}
|
||||||
dctx->expected = 0;
|
dctx->expected = 0;
|
||||||
dctx->stage = ZSTDds_getFrameHeaderSize;
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1420,6 +1428,10 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|||||||
bounds.lowerBound = (int)ZSTD_obm_buffered;
|
bounds.lowerBound = (int)ZSTD_obm_buffered;
|
||||||
bounds.upperBound = (int)ZSTD_obm_stable;
|
bounds.upperBound = (int)ZSTD_obm_stable;
|
||||||
return bounds;
|
return bounds;
|
||||||
|
case ZSTD_d_forceIgnoreChecksum:
|
||||||
|
bounds.lowerBound = (int)ZSTD_d_validateChecksum;
|
||||||
|
bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
|
||||||
|
return bounds;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
bounds.error = ERROR(parameter_unsupported);
|
bounds.error = ERROR(parameter_unsupported);
|
||||||
@@ -1459,6 +1471,10 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
|||||||
CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
|
CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
|
||||||
dctx->outBufferMode = (ZSTD_outBufferMode_e)value;
|
dctx->outBufferMode = (ZSTD_outBufferMode_e)value;
|
||||||
return 0;
|
return 0;
|
||||||
|
case ZSTD_d_forceIgnoreChecksum:
|
||||||
|
CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
|
||||||
|
dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
|
||||||
|
return 0;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
RETURN_ERROR(parameter_unsupported, "");
|
RETURN_ERROR(parameter_unsupported, "");
|
||||||
|
@@ -126,6 +126,8 @@ struct ZSTD_DCtx_s
|
|||||||
XXH64_state_t xxhState;
|
XXH64_state_t xxhState;
|
||||||
size_t headerSize;
|
size_t headerSize;
|
||||||
ZSTD_format_e format;
|
ZSTD_format_e format;
|
||||||
|
ZSTD_forceIgnoreChecksum_e forceIgnoreChecksum; /* User specified: if == 1, will ignore checksums in compressed frame. Default == 0 */
|
||||||
|
U32 validateChecksum; /* if == 1, will validate checksum. Is == 1 if (fParams.checksumFlag == 1) and (forceIgnoreChecksum == 0). */
|
||||||
const BYTE* litPtr;
|
const BYTE* litPtr;
|
||||||
ZSTD_customMem customMem;
|
ZSTD_customMem customMem;
|
||||||
size_t litSize;
|
size_t litSize;
|
||||||
|
21
lib/zstd.h
21
lib/zstd.h
@@ -528,11 +528,13 @@ typedef enum {
|
|||||||
* At the time of this writing, they include :
|
* At the time of this writing, they include :
|
||||||
* ZSTD_d_format
|
* ZSTD_d_format
|
||||||
* ZSTD_d_stableOutBuffer
|
* ZSTD_d_stableOutBuffer
|
||||||
|
* ZSTD_d_forceIgnoreChecksum
|
||||||
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
||||||
* note : never ever use experimentalParam? names directly
|
* note : never ever use experimentalParam? names directly
|
||||||
*/
|
*/
|
||||||
ZSTD_d_experimentalParam1=1000,
|
ZSTD_d_experimentalParam1=1000,
|
||||||
ZSTD_d_experimentalParam2=1001
|
ZSTD_d_experimentalParam2=1001,
|
||||||
|
ZSTD_d_experimentalParam3=1002
|
||||||
|
|
||||||
} ZSTD_dParameter;
|
} ZSTD_dParameter;
|
||||||
|
|
||||||
@@ -1160,6 +1162,12 @@ typedef enum {
|
|||||||
* Decoder cannot recognise automatically this format, requiring this instruction. */
|
* Decoder cannot recognise automatically this format, requiring this instruction. */
|
||||||
} ZSTD_format_e;
|
} ZSTD_format_e;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* Note: this enum controls ZSTD_d_forceIgnoreChecksum */
|
||||||
|
ZSTD_d_validateChecksum = 0,
|
||||||
|
ZSTD_d_ignoreChecksum = 1
|
||||||
|
} ZSTD_forceIgnoreChecksum_e;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/* Note: this enum and the behavior it controls are effectively internal
|
/* Note: this enum and the behavior it controls are effectively internal
|
||||||
* implementation details of the compressor. They are expected to continue
|
* implementation details of the compressor. They are expected to continue
|
||||||
@@ -1690,6 +1698,17 @@ ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowS
|
|||||||
*/
|
*/
|
||||||
#define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2
|
#define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2
|
||||||
|
|
||||||
|
/* ZSTD_d_forceIgnoreChecksum
|
||||||
|
* Experimental parameter.
|
||||||
|
* Default is 0 == disabled. Set to 1 to enable
|
||||||
|
*
|
||||||
|
* Tells the decompressor to skip checksum validation during decompression, regardless
|
||||||
|
* of whether checksumming was specified during compression. This offers some
|
||||||
|
* slight performance benefits, and may be useful for debugging.
|
||||||
|
* Param has values of type ZSTD_forceIgnoreChecksum_e
|
||||||
|
*/
|
||||||
|
#define ZSTD_d_forceIgnoreChecksum ZSTD_d_experimentalParam3
|
||||||
|
|
||||||
/*! ZSTD_DCtx_setFormat() :
|
/*! ZSTD_DCtx_setFormat() :
|
||||||
* Instruct the decoder context about what kind of data to decode next.
|
* Instruct the decoder context about what kind of data to decode next.
|
||||||
* This instruction is mandatory to decode data without a fully-formed header,
|
* This instruction is mandatory to decode data without a fully-formed header,
|
||||||
|
@@ -1754,6 +1754,8 @@ static dRess_t FIO_createDResources(FIO_prefs_t* const prefs, const char* dictFi
|
|||||||
if (ress.dctx==NULL)
|
if (ress.dctx==NULL)
|
||||||
EXM_THROW(60, "Error: %s : can't create ZSTD_DStream", strerror(errno));
|
EXM_THROW(60, "Error: %s : can't create ZSTD_DStream", strerror(errno));
|
||||||
CHECK( ZSTD_DCtx_setMaxWindowSize(ress.dctx, prefs->memLimit) );
|
CHECK( ZSTD_DCtx_setMaxWindowSize(ress.dctx, prefs->memLimit) );
|
||||||
|
CHECK( ZSTD_DCtx_setParameter(ress.dctx, ZSTD_d_forceIgnoreChecksum, !prefs->checksumFlag));
|
||||||
|
|
||||||
ress.srcBufferSize = ZSTD_DStreamInSize();
|
ress.srcBufferSize = ZSTD_DStreamInSize();
|
||||||
ress.srcBuffer = malloc(ress.srcBufferSize);
|
ress.srcBuffer = malloc(ress.srcBufferSize);
|
||||||
ress.dstBufferSize = ZSTD_DStreamOutSize();
|
ress.dstBufferSize = ZSTD_DStreamOutSize();
|
||||||
|
@@ -154,6 +154,19 @@ static void usage_advanced(const char* programName)
|
|||||||
DISPLAYOUT( "--output-dir-mirror DIR : processed files are stored into DIR respecting original directory structure \n");
|
DISPLAYOUT( "--output-dir-mirror DIR : processed files are stored into DIR respecting original directory structure \n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ZSTD_NOCOMPRESS
|
||||||
|
DISPLAYOUT( "--[no-]check : during compression, add XXH64 integrity checksum to frame (default: enabled)");
|
||||||
|
#ifndef ZSTD_NODECOMPRESS
|
||||||
|
DISPLAYOUT( ". If specified with -d, decompressor will ignore/validate checksums in compressed frame (default: validate).");
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef ZSTD_NOCOMPRESS
|
||||||
|
DISPLAYOUT( "--[no-]check : during decompression, ignore/validate checksums in compressed frame (default: validate).");
|
||||||
|
#endif
|
||||||
|
#endif /* ZSTD_NOCOMPRESS */
|
||||||
|
DISPLAYOUT( "\n");
|
||||||
|
|
||||||
DISPLAYOUT( "-- : All arguments after \"--\" are treated as files \n");
|
DISPLAYOUT( "-- : All arguments after \"--\" are treated as files \n");
|
||||||
|
|
||||||
#ifndef ZSTD_NOCOMPRESS
|
#ifndef ZSTD_NOCOMPRESS
|
||||||
@@ -174,7 +187,6 @@ static void usage_advanced(const char* programName)
|
|||||||
DISPLAYOUT( "--size-hint=# optimize compression parameters for streaming input of approximately this size \n");
|
DISPLAYOUT( "--size-hint=# optimize compression parameters for streaming input of approximately this size \n");
|
||||||
DISPLAYOUT( "--target-compressed-block-size=# : generate compressed block of approximately targeted size \n");
|
DISPLAYOUT( "--target-compressed-block-size=# : generate compressed block of approximately targeted size \n");
|
||||||
DISPLAYOUT( "--no-dictID : don't write dictID into header (dictionary compression only) \n");
|
DISPLAYOUT( "--no-dictID : don't write dictID into header (dictionary compression only) \n");
|
||||||
DISPLAYOUT( "--[no-]check : add XXH64 integrity checksum to frame (default: enabled) \n");
|
|
||||||
DISPLAYOUT( "--[no-]compress-literals : force (un)compressed literals \n");
|
DISPLAYOUT( "--[no-]compress-literals : force (un)compressed literals \n");
|
||||||
|
|
||||||
DISPLAYOUT( "--format=zstd : compress files to the .zst format (default) \n");
|
DISPLAYOUT( "--format=zstd : compress files to the .zst format (default) \n");
|
||||||
|
@@ -544,6 +544,45 @@ static int basicUnitTests(U32 const seed, double compressibility)
|
|||||||
if (ZSTD_getErrorCode(r) != ZSTD_error_dstSize_tooSmall) goto _output_error; }
|
if (ZSTD_getErrorCode(r) != ZSTD_error_dstSize_tooSmall) goto _output_error; }
|
||||||
DISPLAYLEVEL(3, "OK \n");
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
|
DISPLAYLEVEL(3, "test%3i : decompress with corrupted checksum : ", testNb++);
|
||||||
|
{ /* create compressed buffer with checksumming enabled */
|
||||||
|
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||||
|
if (!cctx) {
|
||||||
|
DISPLAY("Not enough memory, aborting\n");
|
||||||
|
testResult = 1;
|
||||||
|
goto _end;
|
||||||
|
}
|
||||||
|
CHECK_Z( ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1) );
|
||||||
|
CHECK_VAR(cSize, ZSTD_compress2(cctx,
|
||||||
|
compressedBuffer, compressedBufferSize,
|
||||||
|
CNBuffer, CNBuffSize) );
|
||||||
|
ZSTD_freeCCtx(cctx);
|
||||||
|
}
|
||||||
|
{ /* copy the compressed buffer and corrupt the checksum */
|
||||||
|
size_t r;
|
||||||
|
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||||
|
if (!dctx) {
|
||||||
|
DISPLAY("Not enough memory, aborting\n");
|
||||||
|
testResult = 1;
|
||||||
|
goto _end;
|
||||||
|
}
|
||||||
|
|
||||||
|
((char*)compressedBuffer)[cSize-1] += 1;
|
||||||
|
r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);
|
||||||
|
if (!ZSTD_isError(r)) goto _output_error;
|
||||||
|
if (ZSTD_getErrorCode(r) != ZSTD_error_checksum_wrong) goto _output_error;
|
||||||
|
|
||||||
|
CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_forceIgnoreChecksum, ZSTD_d_ignoreChecksum));
|
||||||
|
r = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize-1);
|
||||||
|
if (!ZSTD_isError(r)) goto _output_error; /* wrong checksum size should still throw error */
|
||||||
|
r = ZSTD_decompressDCtx(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize);
|
||||||
|
if (ZSTD_isError(r)) goto _output_error;
|
||||||
|
|
||||||
|
ZSTD_freeDCtx(dctx);
|
||||||
|
}
|
||||||
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
|
|
||||||
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressBound test with content size missing : ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressBound test with content size missing : ", testNb++);
|
||||||
{ /* create compressed buffer with content size missing */
|
{ /* create compressed buffer with content size missing */
|
||||||
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
ZSTD_CCtx* const cctx = ZSTD_createCCtx();
|
||||||
|
@@ -260,6 +260,13 @@ zstd tmp -c --compress-literals --fast=1 | zstd -t
|
|||||||
zstd tmp -c --compress-literals -19 | zstd -t
|
zstd tmp -c --compress-literals -19 | zstd -t
|
||||||
zstd -b --fast=1 -i0e1 tmp --compress-literals
|
zstd -b --fast=1 -i0e1 tmp --compress-literals
|
||||||
zstd -b --fast=1 -i0e1 tmp --no-compress-literals
|
zstd -b --fast=1 -i0e1 tmp --no-compress-literals
|
||||||
|
println "test: --no-check for decompression"
|
||||||
|
zstd -f tmp -o tmp_corrupt.zst --check
|
||||||
|
zstd -f tmp -o tmp.zst --no-check
|
||||||
|
printf '\xDE\xAD\xBE\xEF' | dd of=tmp_corrupt.zst bs=1 seek=$(($(wc -c < "tmp_corrupt.zst") - 4)) count=4 conv=notrunc # corrupt checksum in tmp
|
||||||
|
zstd -d -f tmp_corrupt.zst --no-check
|
||||||
|
zstd -d -f tmp_corrupt.zst --check --no-check # final flag overrides
|
||||||
|
zstd -d -f tmp.zst --no-check
|
||||||
|
|
||||||
println "\n===> zstdgrep tests"
|
println "\n===> zstdgrep tests"
|
||||||
ln -sf "$ZSTD_BIN" zstdcat
|
ln -sf "$ZSTD_BIN" zstdcat
|
||||||
|
Reference in New Issue
Block a user