feat(compress): validate stable buffers in Rust

Keep the private ZSTD_CCtx and public buffer structures in C while moving the
read-only stable-buffer validation policy behind a scalar ABI. The Rust helper
compares expected and current input pointers and positions without dereferencing
raw pointers, and uses wrapping subtraction for the stable output remainder.
The C wrapper still extracts the context and buffer fields, and the existing
compressStream2 FORWARD_IF_ERROR path remains responsible for propagating the
encoded stability error. The unused endOp parameter is no longer carried into
the validation helper.

Test Plan:
- `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression` -- passed, 309 tests.
- All three requested clippy modes passed before and after `cargo +nightly fmt --manifest-path rust/Cargo.toml`.
- `make -B -C lib -j2 lib` -- passed.
- `make -C tests test-rust-lib-smoke` -- passed.
- `tests/fuzzer -s4560 -t56 -i57 -v` -- passed.
- `make -C tests -j2 test-zstream` -- passed, 84 named plus 5,333 and 8,072 randomized cases.
- `git diff --check` and `git diff --cached --check` -- passed.
- `make -C tests -j2 test-zstream32` -- unavailable because the i686 Rust target is not installed.
This commit is contained in:
2026-07-18 12:35:34 +02:00
parent 2afeb6ec25
commit fe0ace0370
2 changed files with 212 additions and 15 deletions
+17 -15
View File
@@ -105,6 +105,11 @@ ZSTD_inBuffer ZSTD_rust_inBufferForEndFlush(int inBufferMode,
const void* expectedSrc,
size_t expectedSize,
size_t expectedPos);
size_t ZSTD_rust_checkBufferStability(
int inBufferMode, int outBufferMode,
const void* expectedInSrc, size_t expectedInPos,
const void* inputSrc, size_t inputPos,
size_t expectedOutBufferSize, size_t outputSize, size_t outputPos);
/* Context-free compression-parameter selection and sizing leaves live in
* Rust (rust/src/zstd_compress_params.rs). This file retains
@@ -4790,21 +4795,18 @@ ZSTD_setBufferExpectations(ZSTD_CCtx* cctx, const ZSTD_outBuffer* output, const
*/
static size_t ZSTD_checkBufferStability(ZSTD_CCtx const* cctx,
ZSTD_outBuffer const* output,
ZSTD_inBuffer const* input,
ZSTD_EndDirective endOp)
ZSTD_inBuffer const* input)
{
if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {
ZSTD_inBuffer const expect = cctx->expectedInBuffer;
if (expect.src != input->src || expect.pos != input->pos)
RETURN_ERROR(stabilityCondition_notRespected, "ZSTD_c_stableInBuffer enabled but input differs!");
}
(void)endOp;
if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {
size_t const outBufferSize = output->size - output->pos;
if (cctx->expectedOutBufferSize != outBufferSize)
RETURN_ERROR(stabilityCondition_notRespected, "ZSTD_c_stableOutBuffer enabled but output size differs!");
}
return 0;
return ZSTD_rust_checkBufferStability(
(int)cctx->appliedParams.inBufferMode,
(int)cctx->appliedParams.outBufferMode,
cctx->expectedInBuffer.src,
cctx->expectedInBuffer.pos,
input->src,
input->pos,
cctx->expectedOutBufferSize,
output->size,
output->pos);
}
/*
@@ -4972,7 +4974,7 @@ size_t ZSTD_compressStream2_c( ZSTD_CCtx* cctx,
}
/* end of transparent initialization stage */
FORWARD_IF_ERROR(ZSTD_checkBufferStability(cctx, output, input, endOp), "invalid buffers");
FORWARD_IF_ERROR(ZSTD_checkBufferStability(cctx, output, input), "invalid buffers");
/* compression stage */
#ifdef ZSTD_MULTITHREAD
if (cctx->appliedParams.nbWorkers > 0) {