Skip to content

Commit

Permalink
Move has_visited check to the top of the loop in backtrack::Bounded::…
Browse files Browse the repository at this point in the history
…step

This prevents us from executing instructions if they have been executed before, rather than returning after the instruction has already been executed.

Fixes rust-lang#375
  • Loading branch information
adamcrume committed Jun 20, 2017
1 parent 2f18730 commit 6356d1a
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/backtrack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ impl<'a, 'm, 'r, 's, I: Input> Bounded<'a, 'm, 'r, 's, I> {
// from the stack. Namely, if we're pushing a job only to run it
// next, avoid the push and just mutate `ip` (and possibly `at`)
// in place.
if self.has_visited(ip, at) {
return false;
}
match self.prog[ip] {
Match(slot) => {
if slot < self.matches.len() {
Expand Down Expand Up @@ -275,9 +278,6 @@ impl<'a, 'm, 'r, 's, I: Input> Bounded<'a, 'm, 'r, 's, I> {
return false;
}
}
if self.has_visited(ip, at) {
return false;
}
}
}

Expand Down
14 changes: 14 additions & 0 deletions tests/crazy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,20 @@ mat!(negclass_space_comma, r"[^,\s]", ", a", Some((2, 3)));
mat!(negclass_comma_space, r"[^\s,]", " ,a", Some((2, 3)));
mat!(negclass_ascii, r"[^[:alpha:]Z]", "A1", Some((1, 2)));

// Test that repeated empty expressions don't loop forever.
mat!(lazy_many_many, r"((?:.*)*?)=", "a=b", Some((0, 2)));
mat!(lazy_many_optional, r"((?:.?)*?)=", "a=b", Some((0, 2)));
mat!(lazy_one_many_many, r"((?:.*)+?)=", "a=b", Some((0, 2)));
mat!(lazy_one_many_optional, r"((?:.?)+?)=", "a=b", Some((0, 2)));
mat!(lazy_range_min_many, r"((?:.*){1,}?)=", "a=b", Some((0, 2)));
mat!(lazy_range_many, r"((?:.*){1,2}?)=", "a=b", Some((0, 2)));
mat!(greedy_many_many, r"((?:.*)*)=", "a=b", Some((0, 2)));
mat!(greedy_many_optional, r"((?:.?)*)=", "a=b", Some((0, 2)));
mat!(greedy_one_many_many, r"((?:.*)+)=", "a=b", Some((0, 2)));
mat!(greedy_one_many_optional, r"((?:.?)+)=", "a=b", Some((0, 2)));
mat!(greedy_range_min_many, r"((?:.*){1,})=", "a=b", Some((0, 2)));
mat!(greedy_range_many, r"((?:.*){1,2})=", "a=b", Some((0, 2)));

// Test that the DFA can handle pathological cases.
// (This should result in the DFA's cache being flushed too frequently, which
// should cause it to quit and fall back to the NFA algorithm.)
Expand Down

0 comments on commit 6356d1a

Please sign in to comment.