U4-2635 Skip past replaced word when checking
Avoids infinite loop if search and replacement are equal
This commit is contained in:
@@ -1191,11 +1191,13 @@ namespace Umbraco.Core
|
||||
/// <returns>Updated string</returns>
|
||||
public static string Replace(this string source, string oldString, string newString, StringComparison stringComparison)
|
||||
{
|
||||
// Initialised to zero so it can be used as startIndex on first iteration.
|
||||
int index = 0;
|
||||
// This initialisation ensures the first check starts at index zero of the source. On successive checks for
|
||||
// a match, the source is skipped to immediately after the last replaced occurrence for efficiency
|
||||
// and to avoid infinite loops when oldString and newString compare equal.
|
||||
int index = -1 * newString.Length;
|
||||
|
||||
// Determine if there are any matches left in source, starting from last found match.
|
||||
while((index = source.IndexOf(oldString, index, stringComparison)) >= 0)
|
||||
// Determine if there are any matches left in source, starting from just after the result of replacing the last match.
|
||||
while((index = source.IndexOf(oldString, index + newString.Length, stringComparison)) >= 0)
|
||||
{
|
||||
// Remove the old text.
|
||||
source = source.Remove(index, oldString.Length);
|
||||
|
||||
@@ -83,6 +83,9 @@ namespace Umbraco.Tests.CoreStrings
|
||||
[TestCase("Hello this is my string", "hello", "replaced", "replaced this is my string", StringComparison.CurrentCultureIgnoreCase)]
|
||||
[TestCase("Hello this is hello my string", "hello", "replaced", "replaced this is replaced my string", StringComparison.CurrentCultureIgnoreCase)]
|
||||
[TestCase("Hello this is my string", "nonexistent", "replaced", "Hello this is my string", StringComparison.CurrentCultureIgnoreCase)]
|
||||
[TestCase("Hellohello this is my string", "hello", "replaced", "replacedreplaced this is my string", StringComparison.CurrentCultureIgnoreCase)]
|
||||
// Ensure replacing with the same string doesn't cause infinite loop.
|
||||
[TestCase("Hello this is my string", "hello", "hello", "hello this is my string", StringComparison.CurrentCultureIgnoreCase)]
|
||||
public void ReplaceWithStringComparison(string input, string oldString, string newString, string shouldBe, StringComparison stringComparison)
|
||||
{
|
||||
var replaced = input.Replace(oldString, newString, stringComparison);
|
||||
|
||||
Reference in New Issue
Block a user