feat(compress): move sequence-store validation to Rust
Keep the C DEBUGLEVEL gate and delegate the read-only match-length validation through the existing SeqStore ABI. Preserve long-match side-band decoding and the original 3-or-4 byte lower-bound assertion. Test Plan: - cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression - cargo clippy --manifest-path rust/Cargo.toml --no-default-features --features compression --all-targets - cargo +nightly fmt --manifest-path rust/Cargo.toml - make -B -C lib -j2 lib - make -C tests -j2 fuzzer - tests/fuzzer -s4560 -t47 -i48 -v
This commit is contained in:
@@ -277,6 +277,7 @@ void ZSTD_rust_storeLastLiterals(SeqStore_t* seqStorePtr,
|
||||
void ZSTD_rust_resetSeqStore(SeqStore_t* ssPtr);
|
||||
size_t ZSTD_rust_fastSequenceLengthSum(const ZSTD_Sequence* seqBuf,
|
||||
size_t seqBufSize);
|
||||
void ZSTD_rust_validateSeqStore(const SeqStore_t* seqStore, U32 minMatch);
|
||||
size_t ZSTD_rust_convertSequencesNoRepcodes(
|
||||
SeqDef* dstSeqs, const ZSTD_Sequence* inSeqs, size_t nbSequences);
|
||||
BlockSummary ZSTD_rust_get1BlockSummary(const ZSTD_Sequence* seqs,
|
||||
@@ -2348,15 +2349,7 @@ static size_t ZSTD_fastSequenceLengthSum(ZSTD_Sequence const* seqBuf, size_t seq
|
||||
static void ZSTD_validateSeqStore(const SeqStore_t* seqStore, const ZSTD_compressionParameters* cParams)
|
||||
{
|
||||
#if DEBUGLEVEL >= 1
|
||||
const SeqDef* seq = seqStore->sequencesStart;
|
||||
const SeqDef* const seqEnd = seqStore->sequences;
|
||||
size_t const matchLenLowerBound = cParams->minMatch == 3 ? 3 : 4;
|
||||
for (; seq < seqEnd; ++seq) {
|
||||
const ZSTD_SequenceLength seqLength = ZSTD_getSequenceLength(seqStore, seq);
|
||||
assert(seqLength.matchLength >= matchLenLowerBound);
|
||||
(void)seqLength;
|
||||
(void)matchLenLowerBound;
|
||||
}
|
||||
ZSTD_rust_validateSeqStore(seqStore, (U32)cParams->minMatch);
|
||||
#else
|
||||
(void)seqStore;
|
||||
(void)cParams;
|
||||
|
||||
@@ -1151,6 +1151,31 @@ pub unsafe extern "C" fn ZSTD_rust_fastSequenceLengthSum(
|
||||
lit_len_sum.wrapping_add(match_len_sum)
|
||||
}
|
||||
|
||||
/// Validates the match lengths produced in a sequence store. This is the
|
||||
/// Rust leaf for C's `ZSTD_validateSeqStore()`; the C wrapper retains the
|
||||
/// `DEBUGLEVEL` gate so release builds keep the original no-op behavior.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ZSTD_rust_validateSeqStore(
|
||||
seq_store: *const SeqStore_t,
|
||||
min_match: c_uint,
|
||||
) {
|
||||
let seq_store = unsafe { &*seq_store };
|
||||
let match_len_lower_bound = if min_match == 3 { 3 } else { 4 };
|
||||
let nb_sequences =
|
||||
unsafe { seq_store.sequences.offset_from(seq_store.sequencesStart) } as usize;
|
||||
|
||||
for index in 0..nb_sequences {
|
||||
let sequence = unsafe { *seq_store.sequencesStart.add(index) };
|
||||
let mut match_length = sequence.mlBase as usize + MINMATCH;
|
||||
if index == seq_store.longLengthPos as usize
|
||||
&& seq_store.longLengthType == ZSTD_LLT_MATCH_LENGTH
|
||||
{
|
||||
match_length += 0x10000;
|
||||
}
|
||||
assert!(match_length >= match_len_lower_bound);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether all bytes in the input have the same value.
|
||||
///
|
||||
/// This keeps the original C helper's precondition that `src` points to at
|
||||
@@ -3378,6 +3403,45 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validate_seq_store_accepts_ordinary_match_lengths() {
|
||||
let mut fixture = TestSeqStore::new(
|
||||
vec![
|
||||
SeqDef {
|
||||
offBase: 1,
|
||||
litLength: 0,
|
||||
mlBase: 0,
|
||||
},
|
||||
SeqDef {
|
||||
offBase: 1,
|
||||
litLength: 0,
|
||||
mlBase: 1,
|
||||
},
|
||||
],
|
||||
vec![],
|
||||
);
|
||||
let seq_store = fixture.seq_store();
|
||||
|
||||
unsafe { ZSTD_rust_validateSeqStore(&seq_store, 3) };
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validate_seq_store_accounts_for_long_match_metadata() {
|
||||
let mut fixture = TestSeqStore::new(
|
||||
vec![SeqDef {
|
||||
offBase: 1,
|
||||
litLength: 0,
|
||||
mlBase: 0,
|
||||
}],
|
||||
vec![],
|
||||
);
|
||||
let mut seq_store = fixture.seq_store();
|
||||
seq_store.longLengthType = ZSTD_LLT_MATCH_LENGTH;
|
||||
seq_store.longLengthPos = 0;
|
||||
|
||||
unsafe { ZSTD_rust_validateSeqStore(&seq_store, 4) };
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn post_process_rejects_external_count_overflow() {
|
||||
let mut out = [ZSTD_Sequence {
|
||||
|
||||
Reference in New Issue
Block a user