[lib] Validate buffers when ZSTD_c_stable{In,Out}Buffer is set
Adds the validation of the input/output buffers only. They are still unused.
This commit is contained in:
@@ -48,6 +48,7 @@ const char* ERR_getErrorString(ERR_enum code)
|
|||||||
case PREFIX(frameIndex_tooLarge): return "Frame index is too large";
|
case PREFIX(frameIndex_tooLarge): return "Frame index is too large";
|
||||||
case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking";
|
case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking";
|
||||||
case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong";
|
case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong";
|
||||||
|
case PREFIX(srcBuffer_wrong): return "Source buffer is wrong";
|
||||||
case PREFIX(maxCode):
|
case PREFIX(maxCode):
|
||||||
default: return notErrorCode;
|
default: return notErrorCode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ typedef enum {
|
|||||||
ZSTD_error_frameIndex_tooLarge = 100,
|
ZSTD_error_frameIndex_tooLarge = 100,
|
||||||
ZSTD_error_seekableIO = 102,
|
ZSTD_error_seekableIO = 102,
|
||||||
ZSTD_error_dstBuffer_wrong = 104,
|
ZSTD_error_dstBuffer_wrong = 104,
|
||||||
|
ZSTD_error_srcBuffer_wrong = 105,
|
||||||
ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
|
ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
|
||||||
} ZSTD_ErrorCode;
|
} ZSTD_ErrorCode;
|
||||||
|
|
||||||
|
|||||||
@@ -4193,6 +4193,41 @@ size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuf
|
|||||||
return ZSTD_nextInputSizeHint_MTorST(zcs);
|
return ZSTD_nextInputSizeHint_MTorST(zcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* After a compression call set the expected input/output buffer.
|
||||||
|
* This is validated at the start of the next compression call.
|
||||||
|
*/
|
||||||
|
static void ZSTD_setBufferExpectations(ZSTD_CCtx* cctx, ZSTD_outBuffer const* output, ZSTD_inBuffer const* input)
|
||||||
|
{
|
||||||
|
if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {
|
||||||
|
cctx->expectedInBuffer = *input;
|
||||||
|
}
|
||||||
|
if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {
|
||||||
|
cctx->expectedOutBufferSize = output->size - output->pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate that the input/output buffers match the expectations set by
|
||||||
|
* ZSTD_setBufferExpectations.
|
||||||
|
*/
|
||||||
|
static size_t ZSTD_checkBufferStability(ZSTD_CCtx const* cctx,
|
||||||
|
ZSTD_outBuffer const* output,
|
||||||
|
ZSTD_inBuffer const* input,
|
||||||
|
ZSTD_EndDirective endOp)
|
||||||
|
{
|
||||||
|
if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {
|
||||||
|
ZSTD_inBuffer const expect = cctx->expectedInBuffer;
|
||||||
|
if (expect.src != input->src || expect.pos != input->pos || expect.size != input->size)
|
||||||
|
RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer enabled but input differs!");
|
||||||
|
if (endOp != ZSTD_e_end)
|
||||||
|
RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer can only be used with ZSTD_e_end!");
|
||||||
|
}
|
||||||
|
if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {
|
||||||
|
size_t const outBufferSize = output->size - output->pos;
|
||||||
|
if (cctx->expectedOutBufferSize != outBufferSize)
|
||||||
|
RETURN_ERROR(dstBuffer_wrong, "ZSTD_c_stableOutBuffer enabled but output size differs!");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
||||||
ZSTD_outBuffer* output,
|
ZSTD_outBuffer* output,
|
||||||
@@ -4270,9 +4305,13 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
|||||||
cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0;
|
cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0;
|
||||||
cctx->streamStage = zcss_load;
|
cctx->streamStage = zcss_load;
|
||||||
cctx->frameEnded = 0;
|
cctx->frameEnded = 0;
|
||||||
} }
|
}
|
||||||
|
/* Set initial buffer expectations now that we've initialized */
|
||||||
|
ZSTD_setBufferExpectations(cctx, output, input);
|
||||||
|
}
|
||||||
/* end of transparent initialization stage */
|
/* end of transparent initialization stage */
|
||||||
|
|
||||||
|
FORWARD_IF_ERROR(ZSTD_checkBufferStability(cctx, output, input, endOp), "invalid buffers");
|
||||||
/* compression stage */
|
/* compression stage */
|
||||||
#ifdef ZSTD_MULTITHREAD
|
#ifdef ZSTD_MULTITHREAD
|
||||||
if (cctx->appliedParams.nbWorkers > 0) {
|
if (cctx->appliedParams.nbWorkers > 0) {
|
||||||
@@ -4296,11 +4335,13 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
|
|||||||
* flush, or we are out of output space.
|
* flush, or we are out of output space.
|
||||||
*/
|
*/
|
||||||
assert(!forceMaxProgress || flushMin == 0 || output->pos == output->size);
|
assert(!forceMaxProgress || flushMin == 0 || output->pos == output->size);
|
||||||
|
ZSTD_setBufferExpectations(cctx, output, input);
|
||||||
return flushMin;
|
return flushMin;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , "");
|
FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , "");
|
||||||
DEBUGLOG(5, "completed ZSTD_compressStream2");
|
DEBUGLOG(5, "completed ZSTD_compressStream2");
|
||||||
|
ZSTD_setBufferExpectations(cctx, output, input);
|
||||||
return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
|
return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -291,6 +291,10 @@ struct ZSTD_CCtx_s {
|
|||||||
ZSTD_cStreamStage streamStage;
|
ZSTD_cStreamStage streamStage;
|
||||||
U32 frameEnded;
|
U32 frameEnded;
|
||||||
|
|
||||||
|
/* Stable in/out buffer verification */
|
||||||
|
ZSTD_inBuffer expectedInBuffer;
|
||||||
|
size_t expectedOutBufferSize;
|
||||||
|
|
||||||
/* Dictionary */
|
/* Dictionary */
|
||||||
ZSTD_localDict localDict;
|
ZSTD_localDict localDict;
|
||||||
const ZSTD_CDict* cdict;
|
const ZSTD_CDict* cdict;
|
||||||
|
|||||||
Reference in New Issue
Block a user