85 lines · 2.3 KB · Rust
RawDownload
#![no_main] use imara_diff::{Algorithm, Diff, InternedInput};use libfuzzer_sys::{Corpus, fuzz_target}; use libfuzzer_sys::arbitrary::{self, Arbitrary, Unstructured}; /// Keep libFuzzer from spending its whole timeout budget in Myers on oversized,/// repetitive inputs while preserving room for historical regression fixtures.const MAX_FUZZ_INPUT_BYTES: usize = 150 * 1024; #[derive(arbitrary::Arbitrary, Debug)]struct Input<'a> {    before: &'a [u8],    before_str: &'a str,    after: &'a [u8],    after_str: &'a str,} /// Tests all three diff algorithms (Myers, Histogram, MyersMinimal) with:/// - Computing diffs on arbitrary string inputs/// - Postprocessing with no heuristic and line heuristic/// - Unified diff printing/// - Basic queries (count_additions, count_removals, is_added, is_removed)/// - Hunks iterationfn do_fuzz(    Input {        before,        before_str,        after,        after_str,    }: Input<'_>,) {    // Create interned input    let input = InternedInput::new(before, after);     // Test all three diff algorithms    for algorithm in [        Algorithm::Histogram,        Algorithm::Myers,        Algorithm::MyersMinimal,    ] {        // Compute diff        let mut diff = Diff::compute(algorithm, &input);         // Test basic queries        let _ = diff.count_additions();        let _ = diff.count_removals();         // Test hunks iteration        for hunk in diff.hunks() {            let _ = hunk.is_pure_insertion();            let _ = hunk.is_pure_removal();            let _ = hunk.invert();        }         // Test postprocessing with no heuristic        diff.postprocess_no_heuristic(&input);         // Test postprocessing with line heuristic        diff.postprocess_lines(&input);    }     let input = InternedInput::new(before_str, after_str);    let mut word_input = InternedInput::default();    let mut word_diff = Diff::default();     let diff = Diff::compute(Algorithm::Myers, &input);    for hunk in diff.hunks() {        hunk.latin_word_diff(&input, &mut word_input, &mut word_diff);    }} fuzz_target!(|data: &[u8]| -> Corpus {    if data.len() > MAX_FUZZ_INPUT_BYTES {        return Corpus::Reject;    }     let Ok(input) = Input::arbitrary_take_rest(Unstructured::new(data)) else {        return Corpus::Reject;    };     do_fuzz(input);    Corpus::Keep});