Skip to content

Commit d12f79a

Browse files
authored
Fix overaggressive CanBeMadeAtomic check for Set + Notone (#33409)
We're erroneously converting a set loop to be atomic when it's followed by a notone where the notone's character is in the set. But if we for example have `[ab]*[^a]`, we can't make the loop atomic, because the `[ab]*` can actually give back something (a `b`) that the `[^a]` will match. The fix is simply to delete the erroneous, overaggressive checks.
1 parent fb01e2c commit d12f79a

File tree

3 files changed

+6
-4
lines changed

3 files changed

+6
-4
lines changed

src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexNode.cs

-4
Original file line numberDiff line numberDiff line change
@@ -1541,10 +1541,6 @@ private static bool CanBeMadeAtomic(RegexNode node, RegexNode subsequent, uint m
15411541
case Onelazy when subsequent.M > 0 && !RegexCharClass.CharInClass(subsequent.Ch, node.Str!):
15421542
case Oneloop when subsequent.M > 0 && !RegexCharClass.CharInClass(subsequent.Ch, node.Str!):
15431543
case Oneloopatomic when subsequent.M > 0 && !RegexCharClass.CharInClass(subsequent.Ch, node.Str!):
1544-
case Notone when RegexCharClass.CharInClass(subsequent.Ch, node.Str!):
1545-
case Notonelazy when subsequent.M > 0 && RegexCharClass.CharInClass(subsequent.Ch, node.Str!):
1546-
case Notoneloop when subsequent.M > 0 && RegexCharClass.CharInClass(subsequent.Ch, node.Str!):
1547-
case Notoneloopatomic when subsequent.M > 0 && RegexCharClass.CharInClass(subsequent.Ch, node.Str!):
15481544
case Multi when !RegexCharClass.CharInClass(subsequent.Str![0], node.Str!):
15491545
case Set when !RegexCharClass.MayOverlap(node.Str!, subsequent.Str!):
15501546
case Setlazy when subsequent.M > 0 && !RegexCharClass.MayOverlap(node.Str!, subsequent.Str!):

src/libraries/System.Text.RegularExpressions/tests/Regex.Groups.Tests.cs

+2
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,8 @@ public static IEnumerable<object[]> Groups_Basic_TestData()
733733
yield return new object[] { null, @"(?:a{2}?){3}?", "aaaaaaaaa", RegexOptions.None, new string[] { "aaaaaa" } };
734734
yield return new object[] { null, @"(?:(?:[ab]c[de]f){3}){2}", "acdfbcdfacefbcefbcefbcdfacdef", RegexOptions.None, new string[] { "acdfbcdfacefbcefbcefbcdf" } };
735735
yield return new object[] { null, @"(?:(?:[ab]c[de]f){3}hello){2}", "aaaaaacdfbcdfacefhellobcefbcefbcdfhellooooo", RegexOptions.None, new string[] { "acdfbcdfacefhellobcefbcefbcdfhello" } };
736+
yield return new object[] { null, @"CN=(.*[^,]+).*", "CN=localhost", RegexOptions.Singleline, new string[] { "CN=localhost", "localhost" } };
737+
736738
// Nested atomic
737739
yield return new object[] { null, @"(?>abc[def]gh(i*))", "123abceghiii456", RegexOptions.None, new string[] { "abceghiii", "iii" } };
738740

src/libraries/System.Text.RegularExpressions/tests/RegexReductionTests.cs

+4
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,10 @@ public void PatternsReduceIdentically(string pattern1, string pattern2)
375375
[InlineData("a*a*?", "a*")]
376376
[InlineData("a*?a*", "a*")]
377377
[InlineData("a*[^a]*", "a*")]
378+
[InlineData("[ab]*[^a]", "(?>[ab]*)[^a]")]
379+
[InlineData("[ab]*[^a]*", "(?>[ab]*)[^a]*")]
380+
[InlineData("[ab]*[^a]*?", "(?>[ab]*)[^a]*?")]
381+
[InlineData("[ab]*(?>[^a]*)", "(?>[ab]*)(?>[^a]*)")]
378382
[InlineData("[^a]*a*", "a*")]
379383
[InlineData("a{2147483646}a", "a{2147483647}")]
380384
[InlineData("a{2147483647}a", "a{2147483647}")]

0 commit comments

Comments
 (0)