Remove implicit anchoring optimization from Regex (#42408)
authorStephen Toub <stoub@microsoft.com>
Sat, 19 Sep 2020 00:58:44 +0000 (20:58 -0400)
committerGitHub <noreply@github.com>
Sat, 19 Sep 2020 00:58:44 +0000 (17:58 -0700)
commita3f643be8fdd5759f78d982c961959f0074c1288
tree7917ee6f0bb3af6819ab9e9353fa5289973a9104
parente74c773cc2858cefb57fc0ff5d2fe23288f82925
Remove implicit anchoring optimization from Regex (#42408)

* Remove implicit anchoring optimization from Regex

In .NET 5 we added a bunch of optimizations to Regex.  One of them was a transform that optimized for the case where the pattern begins with `.*`.  If it does, then we insert an implicit anchor at the beginning in order to avoid unnecessary backtracking.  Imagine the pattern `.*a` and the pattern `bcdefghijklmnopqrstuvwxyz`.  This is going to start matching at `b`, find the next newline, and then backtrack from there looking for the `a`; it won't find it and will backtrack all the way, failing the match at that position.  At that point it'll bump to the next position, starting at `c`, and do it all over.  It'll fail, backtrack all the way, and bump again, starting at `d`, and doing it all over.  Etc.  The optimization recognizes that since `.` will match anything other than newline, after it fails to match at the first position, we can just skip all subsequent positions until the next newline, as they're all going to fail.

However, the optimization failed to take into account that someone can explicitly start a match in the middle of the provided text.  In that case, the implicitly added anchor will fail the match in the actual "Go" matching logic.

There are safe ways to do this optimization, e.g. introducing a variant of these anchors that let FindFirstChar skip ahead but that aren't considered for Go's matching purposes, but we can look at employing those for .NET 6.  For now for .NET 5, this commit just deletes the faulty optimization and adds a few tests that were failing it.

* Address PR feedback
src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs
src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs
src/libraries/System.Text.RegularExpressions/tests/Regex.MultipleMatches.Tests.cs