fix(compress): restore C fallback for unsupported CCtx strategies
ZSTD_compressCCtx was selecting the Rust frame path for every compression level. For source sizes that resolve to lazy or optimal strategies, that path fell through to fast matching and could produce a different frame, including the CCtx reuse regression caught by fuzzer test 56. Query the source-size-dependent C parameters before preparing the context. Keep fast and double-fast strategies on the existing Rust path, while routing all other strategies through ZSTD_compress_usingDict with no dictionary so the original simple API initializes requested parameters and C match state. Test Plan: - `make -B -C tests -j2 fuzzer` -- passed - `./tests/fuzzer -s4560 -t56 -i56 -v` -- passed - `cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression` -- 253 passed - required clippy normal, benches, and tests checks -- passed - `cargo +nightly fmt --manifest-path rust/Cargo.toml` -- passed - `git diff --check` and `git diff --cached --check` -- passed
This commit is contained in:
@@ -40,9 +40,20 @@ unsafe extern "C" {
|
||||
src_size: usize,
|
||||
compression_level: c_int,
|
||||
) -> usize;
|
||||
fn ZSTD_rust_compressCCtxStrategy(src_size: usize, compression_level: c_int) -> c_int;
|
||||
fn ZSTD_rust_resetCCtxForSimpleCompressionSession(cctx: *mut c_void) -> usize;
|
||||
fn ZSTD_rust_markSimpleCompression2Complete(cctx: *mut c_void);
|
||||
fn ZSTD_rust_simpleCompress2Level(cctx: *const c_void) -> c_int;
|
||||
fn ZSTD_compress_usingDict(
|
||||
cctx: *mut c_void,
|
||||
dst: *mut c_void,
|
||||
dst_capacity: usize,
|
||||
src: *const c_void,
|
||||
src_size: usize,
|
||||
dict: *const c_void,
|
||||
dict_size: usize,
|
||||
compression_level: c_int,
|
||||
) -> usize;
|
||||
fn ZSTD_rust_simpleCompressStream2Level(cctx: *const c_void) -> c_int;
|
||||
fn ZSTD_compress2_c(
|
||||
cctx: *mut c_void,
|
||||
@@ -565,8 +576,8 @@ pub unsafe extern "C" fn ZSTD_compress(
|
||||
///
|
||||
/// The public contract deliberately ignores all advanced context parameters.
|
||||
/// C performs the context reset because the private `ZSTD_CCtx_s` layout is
|
||||
/// still configuration-dependent; the frame compressor itself is entirely
|
||||
/// Rust-owned and does not inspect the context.
|
||||
/// still configuration-dependent. Strategies not yet implemented by the
|
||||
/// Rust frame compressor use the original C simple API before that reset.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ZSTD_compressCCtx(
|
||||
cctx: *mut c_void,
|
||||
@@ -581,6 +592,21 @@ pub unsafe extern "C" fn ZSTD_compressCCtx(
|
||||
}
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
let strategy = unsafe { ZSTD_rust_compressCCtxStrategy(src_size, compression_level) };
|
||||
if strategy != ZSTD_FAST && strategy != ZSTD_DFAST {
|
||||
return unsafe {
|
||||
ZSTD_compress_usingDict(
|
||||
cctx,
|
||||
dst,
|
||||
dst_capacity,
|
||||
src,
|
||||
src_size,
|
||||
ptr::null(),
|
||||
0,
|
||||
compression_level,
|
||||
)
|
||||
};
|
||||
}
|
||||
let reset = unsafe { ZSTD_rust_resetCCtxForSimpleCompression(cctx) };
|
||||
if ERR_isError(reset) {
|
||||
return reset;
|
||||
|
||||
Reference in New Issue
Block a user