| 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] |
| 7 | fn invalid_byte_classes() { |
| 8 | let data = include_bytes!( |
| 9 | "testdata/deserialize_dense_crash-9486fb7c8a93b12c12a62166b43d31640c0208a9" , |
| 10 | ); |
| 11 | let _ = fuzz_run(data); |
| 12 | } |
| 13 | |
| 14 | #[test] |
| 15 | fn 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. |
| 24 | fn 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(®ex_automata::Input::new(haystack)); |
| 51 | Some(()) |
| 52 | } |
| 53 | |