-
Notifications
You must be signed in to change notification settings - Fork 416
/
ast_diff_dense_dfa.rs
65 lines (55 loc) · 1.86 KB
/
ast_diff_dense_dfa.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#![no_main]
use regex_automata::Input;
use {
libfuzzer_sys::{fuzz_target, Corpus},
regex_automata::{
dfa::{dense::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().dfa_size_limit(Some(1 << 20));
let Ok(re) = RegexBuilder::new().dense(config).build(&pattern) else {
return Corpus::Reject;
};
if let Ok(maybe_match) = re.try_search(&Input::new(&pattern)) {
assert_eq!(
maybe_match.is_some(),
baseline.is_match(&mut cache, &data.haystack)
);
let found2 = baseline.find(&mut cache, &data.haystack);
if let Some(found1) = maybe_match {
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) });