1// This test was found by a fuzzer input that crafted a way to provide
2// an invalid serialization of ByteClasses that passed our verification.
3// Specifically, the verification step in the deserialization of ByteClasses
4// used an iterator that depends on part of the serialized bytes being correct.
5// (Specifically, the encoding of the number of classes.)
6#[test]
7fn invalid_byte_classes() {
8 let data = include_bytes!(
9 "testdata/deserialize_dense_crash-9486fb7c8a93b12c12a62166b43d31640c0208a9",
10 );
11 let _ = fuzz_run(data);
12}
13
14#[test]
15fn invalid_byte_classes_min() {
16 let data = include_bytes!(
17 "testdata/deserialize_dense_minimized-from-9486fb7c8a93b12c12a62166b43d31640c0208a9",
18 );
19 let _ = fuzz_run(data);
20}
21
22// This is the code from the fuzz target. Kind of sucks to duplicate it here,
23// but this is fundamentally how we interpret the date.
24fn fuzz_run(given_data: &[u8]) -> Option<()> {
25 use regex_automata::dfa::Automaton;
26
27 if given_data.len() < 2 {
28 return None;
29 }
30 let haystack_len = usize::from(given_data[0]);
31 let haystack = given_data.get(1..1 + haystack_len)?;
32 let given_dfa_bytes = given_data.get(1 + haystack_len..)?;
33
34 // We help the fuzzer along by adding a preamble to the bytes that should
35 // at least make these first parts valid. The preamble expects a very
36 // specific sequence of bytes, so it makes sense to just force this.
37 let label = "rust-regex-automata-dfa-dense\x00\x00\x00";
38 assert_eq!(0, label.len() % 4);
39 let endianness_check = 0xFEFFu32.to_ne_bytes().to_vec();
40 let version_check = 2u32.to_ne_bytes().to_vec();
41 let mut dfa_bytes: Vec<u8> = vec![];
42 dfa_bytes.extend(label.as_bytes());
43 dfa_bytes.extend(&endianness_check);
44 dfa_bytes.extend(&version_check);
45 dfa_bytes.extend(given_dfa_bytes);
46 // This is the real test: checking that any input we give to
47 // DFA::from_bytes will never result in a panic.
48 let (dfa, _) =
49 regex_automata::dfa::dense::DFA::from_bytes(&dfa_bytes).ok()?;
50 let _ = dfa.try_search_fwd(&regex_automata::Input::new(haystack));
51 Some(())
52}
53