Skip to content

Commit

Permalink
hybrid diff
Browse files Browse the repository at this point in the history
  • Loading branch information
addisoncrump committed May 8, 2024
1 parent 5b9ab60 commit 2a5d8aa
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
4 changes: 4 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ path = "fuzz_targets/ast_diff_onepass_dfa.rs"
name = "ast_diff_sparse_dfa"
path = "fuzz_targets/ast_diff_sparse_dfa.rs"

[[bin]]
name = "ast_diff_hybrid"
path = "fuzz_targets/ast_diff_hybrid.rs"

[[bin]]
name = "ast_diff_nfas"
path = "fuzz_targets/ast_diff_nfas.rs"
Expand Down
63 changes: 63 additions & 0 deletions fuzz/fuzz_targets/ast_diff_hybrid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#![no_main]

use {
libfuzzer_sys::{fuzz_target, Corpus},
regex_automata::{
hybrid::{dfa::DFA, regex::Builder as RegexBuilder},
nfa::thompson::{pikevm::PikeVM as NfaRegex, NFA},
},
regex_syntax::ast::Ast,
};

#[derive(Eq, PartialEq, arbitrary::Arbitrary)]
struct FuzzData {
ast: Ast,
haystack: String,
}

impl std::fmt::Debug for FuzzData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut builder = f.debug_struct("FuzzData");
builder.field("ast", &format!("{}", self.ast));
builder.field("haystack", &self.haystack);
builder.finish()
}
}

fn do_fuzz(data: FuzzData) -> Corpus {
let _ = env_logger::try_init();

let pattern = format!("{}", data.ast);
let config = NFA::config().nfa_size_limit(Some(1 << 20));
let Ok(nfa) = NFA::compiler().configure(config).build(&pattern) else {
return Corpus::Reject;
};
let Ok(baseline) = NfaRegex::new_from_nfa(nfa) else {
return Corpus::Reject;
};
let mut cache = baseline.create_cache();

let config = DFA::config().cache_capacity(1 << 20);
let Ok(re) = RegexBuilder::new().dfa(config).build(&pattern) else {
return Corpus::Reject;
};
let mut hybrid_cache = re.create_cache();

assert_eq!(
re.is_match(&mut hybrid_cache, &data.haystack),
baseline.is_match(&mut cache, &data.haystack)
);
let found1 = re.find(&mut hybrid_cache, &data.haystack);
let found2 = baseline.find(&mut cache, &data.haystack);
if let Some(found1) = found1 {
let found2 = found2.expect("Found in target, but not in baseline!");
assert_eq!(found1.start(), found2.start());
assert_eq!(found1.end(), found2.end());
}

// no captures

Corpus::Keep
}

fuzz_target!(|data: FuzzData| -> Corpus { do_fuzz(data) });

0 comments on commit 2a5d8aa

Please sign in to comment.