diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index addb0208..fcf1767d 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -94,11 +94,18 @@ static size_t ZSTD_startingInputLength(ZSTD_format_e format) return startingInputLength; } +static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx) +{ + assert(dctx->streamStage == zdss_init); + dctx->format = ZSTD_f_zstd1; + dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; + dctx->outBufferMode = ZSTD_obm_buffered; + dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum; +} + static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx) { - dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */ dctx->staticSize = 0; - dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; dctx->ddict = NULL; dctx->ddictLocal = NULL; dctx->dictEnd = NULL; @@ -113,8 +120,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx) dctx->noForwardProgress = 0; dctx->oversizedDuration = 0; dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); - dctx->outBufferMode = ZSTD_obm_buffered; - dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum; + ZSTD_DCtx_resetParameters(dctx); dctx->validateChecksum = 1; #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION dctx->dictContentEndForFuzzing = NULL; @@ -1454,6 +1460,26 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value) RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \ } +size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value) +{ + switch (param) { + case ZSTD_d_windowLogMax: + *value = ZSTD_highbit32((U32)dctx->maxWindowSize); + return 0; + case ZSTD_d_format: + *value = dctx->format; + return 0; + case ZSTD_d_stableOutBuffer: + *value = dctx->outBufferMode; + return 0; + case ZSTD_d_forceIgnoreChecksum: + *value = dctx->forceIgnoreChecksum; + return 0; + default:; + } + RETURN_ERROR(parameter_unsupported, ""); +} + size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value) { RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, ""); @@ -1491,8 +1517,7 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset) || (reset == ZSTD_reset_session_and_parameters) ) { RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, ""); ZSTD_clearDict(dctx); - dctx->format = ZSTD_f_zstd1; - dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; + ZSTD_DCtx_resetParameters(dctx); } return 0; } diff --git a/lib/zstd.h b/lib/zstd.h index 0a93ee6f..9e570b42 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -1739,6 +1739,13 @@ ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* pre */ ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize); +/*! ZSTD_DCtx_getParameter() : + * Get the requested decompression parameter value, selected by enum ZSTD_dParameter, + * and store it into int* value. + * @return : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value); + /* ZSTD_d_format * experimental parameter, * allowing selection between ZSTD_format_e input compression formats diff --git a/tests/fuzzer.c b/tests/fuzzer.c index 9749c6df..8b10078a 100644 --- a/tests/fuzzer.c +++ b/tests/fuzzer.c @@ -2488,6 +2488,34 @@ static int basicUnitTests(U32 const seed, double compressibility) ZSTD_freeDCtx(dctx); } + DISPLAYLEVEL(3, "test%3i : Decompression parameter reset test : ", testNb++); + { + ZSTD_DCtx* const dctx = ZSTD_createDCtx(); + /* Attempt to future proof this to new parameters. */ + int const maxParam = 2000; + int param; + if (ZSTD_d_experimentalParam3 > maxParam) goto _output_error; + for (param = 0; param < maxParam; ++param) { + ZSTD_dParameter dParam = (ZSTD_dParameter)param; + ZSTD_bounds bounds = ZSTD_dParam_getBounds(dParam); + int value1; + int value2; + int check; + if (ZSTD_isError(bounds.error)) + continue; + CHECK(ZSTD_DCtx_getParameter(dctx, dParam, &value1)); + value2 = (value1 != bounds.lowerBound) ? bounds.lowerBound : bounds.upperBound; + CHECK(ZSTD_DCtx_setParameter(dctx, dParam, value2)); + CHECK(ZSTD_DCtx_getParameter(dctx, dParam, &check)); + if (check != value2) goto _output_error; + CHECK(ZSTD_DCtx_reset(dctx, ZSTD_reset_parameters)); + CHECK(ZSTD_DCtx_getParameter(dctx, dParam, &check)); + if (check != value1) goto _output_error; + } + ZSTD_freeDCtx(dctx); + } + DISPLAYLEVEL(3, "OK \n"); + /* block API tests */ { ZSTD_CCtx* const cctx = ZSTD_createCCtx(); ZSTD_DCtx* const dctx = ZSTD_createDCtx();