@@ -2344,10 +2344,17 @@ impl<'a> DFA<&'a [u32]> {
23442344 // table, match states and accelerators below. If any validation fails,
23452345 // then we return an error.
23462346 let ( dfa, nread) = unsafe { DFA :: from_bytes_unchecked ( slice) ? } ;
2347+ // Note that validation order is important here:
2348+ //
2349+ // * `MatchState::validate` can be called with an untrusted DFA.
2350+ // * `TransistionTable::validate` uses `dfa.ms` through `match_len`.
2351+ // * `StartTable::validate` needs a valid transition table.
2352+ //
2353+ // So... validate the match states first.
2354+ dfa. accels . validate ( ) ?;
2355+ dfa. ms . validate ( & dfa) ?;
23472356 dfa. tt . validate ( & dfa) ?;
23482357 dfa. st . validate ( & dfa) ?;
2349- dfa. ms . validate ( & dfa) ?;
2350- dfa. accels . validate ( ) ?;
23512358 // N.B. dfa.special doesn't have a way to do unchecked deserialization,
23522359 // so it has already been validated.
23532360 for state in dfa. states ( ) {
@@ -5235,7 +5242,10 @@ mod tests {
52355242 assert_eq ! ( Err ( expected) , got) ;
52365243 }
52375244
5238- // This panics in TransitionTable::validate if the match states are not validated first.
5245+ // This panics in `TransitionTable::validate` if the match states are not
5246+ // validated first.
5247+ //
5248+ // See: https://github.com/rust-lang/regex/pull/1295
52395249 #[ test]
52405250 fn regression_validation_order ( ) {
52415251 let mut dfa = DFA :: new ( "abc" ) . unwrap ( ) ;
0 commit comments