Skip to content

Commit

Permalink
Fix length check for Regex BOL FindFirstChar optimization (#55574)
Browse files Browse the repository at this point in the history
For a beginning-of-line anchor, in FindFirstChar we use IndexOf to quickly skip ahead to the next \n.  But we neglected to check to see whether that brought us past an explicitly specified end position.  This just adds the missing check.
  • Loading branch information
stephentoub authored Jul 13, 2021
1 parent a38fc2f commit ce09822
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1240,19 +1240,21 @@ protected void GenerateFindFirstChar()
{
Stloc(newlinePos);

// if (newlinePos == -1)
// if (newlinePos == -1 || newlinePos + 1 > runtextend)
// {
// runtextpos = runtextend;
// return false;
// }
Label foundNextLine = DefineLabel();
Ldloc(newlinePos);
Ldc(-1);
Bne(foundNextLine);
BrFar(returnFalse);
Beq(returnFalse);
Ldloc(newlinePos);
Ldc(1);
Add();
Ldloc(_runtextendLocal);
Bgt(returnFalse);

// runtextpos = newlinePos + 1;
MarkLabel(foundNextLine);
Ldloc(newlinePos);
Ldc(1);
Add();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ protected override bool FindFirstChar()
if (runtextpos > runtextbeg && runtext![runtextpos - 1] != '\n')
{
int newline = runtext.IndexOf('\n', runtextpos);
if (newline == -1)
if (newline == -1 || newline + 1 > runtextend)
{
runtextpos = runtextend;
return false;
Expand Down Expand Up @@ -457,7 +457,7 @@ protected override bool FindFirstChar()
if (!_code.LeadingCharClasses[0].CaseInsensitive)
{
// singleton, left-to-right, case-sensitive
int i = runtext.AsSpan(runtextpos, runtextend - runtextpos).IndexOf(ch);
int i = span.IndexOf(ch);
if (i >= 0)
{
runtextpos += i;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ public static IEnumerable<object[]> Match_Basic_TestData()
// Using beginning/end of string chars \A, \Z: Actual - "\\Aaaa\\w+zzz\\Z"
yield return new object[] { @"\Aaaa\w+zzz\Z", "aaaasdfajsdlfjzzza", RegexOptions.None, 0, 18, false, string.Empty };

// Anchors and multiline
yield return new object[] { @"^A$", "ABC\n", RegexOptions.Multiline, 0, 2, false, string.Empty };

// Using beginning/end of string chars \A, \Z: Actual - "\\Aaaa\\w+zzz\\Z"
yield return new object[] { @"\A(line2\n)line3\Z", "line2\nline3\n", RegexOptions.Multiline, 0, 12, true, "line2\nline3" };

Expand Down Expand Up @@ -813,7 +816,7 @@ public static IEnumerable<object[]> Match_Advanced_TestData()
}
};

// Mutliline
// Multiline
yield return new object[]
{
"(line2$\n)line3", "line1\nline2\nline3\n\nline4", RegexOptions.Multiline, 0, 24,
Expand All @@ -824,7 +827,7 @@ public static IEnumerable<object[]> Match_Advanced_TestData()
}
};

// Mutliline
// Multiline
yield return new object[]
{
"(line2\n^)line3", "line1\nline2\nline3\n\nline4", RegexOptions.Multiline, 0, 24,
Expand All @@ -835,7 +838,7 @@ public static IEnumerable<object[]> Match_Advanced_TestData()
}
};

// Mutliline
// Multiline
yield return new object[]
{
"(line3\n$\n)line4", "line1\nline2\nline3\n\nline4", RegexOptions.Multiline, 0, 24,
Expand All @@ -846,7 +849,7 @@ public static IEnumerable<object[]> Match_Advanced_TestData()
}
};

// Mutliline
// Multiline
yield return new object[]
{
"(line3\n^\n)line4", "line1\nline2\nline3\n\nline4", RegexOptions.Multiline, 0, 24,
Expand All @@ -857,7 +860,7 @@ public static IEnumerable<object[]> Match_Advanced_TestData()
}
};

// Mutliline
// Multiline
yield return new object[]
{
"(line2$\n^)line3", "line1\nline2\nline3\n\nline4", RegexOptions.Multiline, 0, 24,
Expand Down

0 comments on commit ce09822

Please sign in to comment.