diff --git a/lib/compress/zstd_compress.c b/lib/compress/zstd_compress.c index f434d7249..e2b9eb83d 100644 --- a/lib/compress/zstd_compress.c +++ b/lib/compress/zstd_compress.c @@ -604,6 +604,7 @@ size_t ZSTD_compressStream2_c(ZSTD_CCtx* cctx, ZSTD_EndDirective endOp); int ZSTD_rust_simpleCompress2Level(const void* cctx, size_t srcSize); int ZSTD_rust_simpleCompressStream2Level(const void* cctx, size_t srcSize); +U32 ZSTD_rust_limitNextToUpdate(U32 curr, U32 nextToUpdate); void ZSTD_rust_reduceIndex(U32* hashTable, U32 hashSize, U32* chainTable, U32 chainSize, U32* hashTable3, U32 hashSize3, @@ -4721,8 +4722,7 @@ static void ZSTD_rust_buildSeqStore_prepareMatchState(void* context, const BYTE* const istart = (const BYTE*)src; const U32 curr = (U32)(istart-base); if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1)); - if (curr > ms->nextToUpdate + 384) - ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384)); + ms->nextToUpdate = ZSTD_rust_limitNextToUpdate(curr, ms->nextToUpdate); } } diff --git a/rust/src/zstd_compress.rs b/rust/src/zstd_compress.rs index 552c408f4..4d3d7e5f5 100644 --- a/rust/src/zstd_compress.rs +++ b/rust/src/zstd_compress.rs @@ -5238,6 +5238,26 @@ pub extern "C" fn ZSTD_rust_windowNeedOverflowCorrection( ) as u32 } +#[inline] +fn limit_next_to_update(curr: u32, next_to_update: u32) -> u32 { + let const_gap = 384u32; + let const_step = 192u32; + if curr > next_to_update.wrapping_add(const_gap) { + curr.wrapping_sub(const_step.min(curr.wrapping_sub(next_to_update).wrapping_sub(const_gap))) + } else { + next_to_update + } +} + +/// Limit a stale matchfinder update point after a very long match. +/// +/// C computes the source index against its private window base; Rust owns the +/// wrapping U32 threshold and bounded catch-up arithmetic. +#[no_mangle] +pub extern "C" fn ZSTD_rust_limitNextToUpdate(curr: u32, next_to_update: u32) -> u32 { + limit_next_to_update(curr, next_to_update) +} + #[inline] fn next_input_size_hint( in_buffer_mode: c_int, @@ -10803,6 +10823,15 @@ mod tests { assert!(!window_need_overflow_correction(27, true, 1024, false)); } + #[test] + fn limit_next_to_update_preserves_threshold_and_bounded_catch_up() { + assert_eq!(limit_next_to_update(884, 500), 500); + assert_eq!(limit_next_to_update(885, 500), 884); + assert_eq!(limit_next_to_update(1000, 500), 884); + assert_eq!(limit_next_to_update(1200, 500), 1008); + assert_eq!(ZSTD_rust_limitNextToUpdate(300, u32::MAX - 100), 283); + } + #[test] fn window_overflow_need_scales_the_frequency_with_correction_count() { assert!(window_can_overflow_correct(27, 3, 16, 0, 0));