Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaryam Ariyan <maryam.ariyan@microsoft.com>2018-03-23 19:29:55 +0300
committerJan Kotas <jkotas@microsoft.com>2018-03-23 22:08:28 +0300
commit9df718944af1a0ff17deac41810fc0a2a391d264 (patch)
tree9ffb75b6e534ece45f43e0b635e1abb9372b04f7 /src
parent85b8a261218078071e6ab147e37521b92948ea79 (diff)
Fixes StringBuilder unbounded size growth in Clear() when we use a mix of Append and Insert (#16926)
* Fixing Clear infinitely growing when we combine usage of Insert and Append. Fixes #27625 * Move debug code to StringBuilder.Debug.cs and Applied code review feedback * Adding missing debug condition check * Adding comments and moving Condition on projitems after filename * Moving the infinite capacity growth fix to Length setter * Removing originalCapacity and Debug.Assert * Applying PR feedbacks * Minor cleanup * simplifying to single loop * keeping just one method for ShowChunks function Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
Diffstat (limited to 'src')
-rw-r--r--src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems1
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs39
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs9
3 files changed, 44 insertions, 5 deletions
diff --git a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
index 270d06d3c..f4f8dd32a 100644
--- a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
+++ b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
@@ -521,6 +521,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Text\Latin1Encoding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\NormalizationForm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\StringBuilder.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Text\StringBuilder.Debug.cs" Condition="'$(Configuration)' == 'Debug'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\UnicodeEncoding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\UTF32Encoding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\UTF7Encoding.cs" />
diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs
new file mode 100644
index 000000000..c2c8c9f7f
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.Serialization;
+
+namespace System.Text
+{
+ public sealed partial class StringBuilder
+ {
+ private void ShowChunks(int maxChunksToShow = 10)
+ {
+ int count = 0;
+ StringBuilder head = this, current = this;
+ while (current != null)
+ {
+ if (count < maxChunksToShow)
+ {
+ count++;
+ }
+ else
+ {
+ head = head.m_ChunkPrevious;
+ }
+ current = current.m_ChunkPrevious;
+ }
+ current = head;
+ string[] chunks = new string[count];
+ for (int i = count; i > 0; i--)
+ {
+ chunks[i - 1] = new string(current.m_ChunkChars).Replace('\0', '.');
+ current = current.m_ChunkPrevious;
+ }
+ Debug.WriteLine('|' + string.Join('|', chunks) + '|');
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
index 185e5a46e..1a3208490 100644
--- a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
@@ -462,13 +462,10 @@ namespace System.Text
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_SmallCapacity);
}
- int originalCapacity = Capacity;
-
if (value == 0 && m_ChunkPrevious == null)
{
m_ChunkLength = 0;
m_ChunkOffset = 0;
- Debug.Assert(Capacity >= originalCapacity);
return;
}
@@ -485,7 +482,10 @@ namespace System.Text
{
// We crossed a chunk boundary when reducing the Length. We must replace this middle-chunk with a new larger chunk,
// to ensure the original capacity is preserved.
- int newLen = originalCapacity - chunk.m_ChunkOffset;
+
+ // Avoid possible infinite capacity growth. See https://github.com/dotnet/coreclr/pull/16926
+ int capacityToPreserve = Math.Min(Capacity, Math.Max(Length * 6 / 5, m_ChunkChars.Length));
+ int newLen = capacityToPreserve - chunk.m_ChunkOffset;
char[] newArray = new char[newLen];
Debug.Assert(newLen > chunk.m_ChunkChars.Length, "The new chunk should be larger than the one it is replacing.");
@@ -498,7 +498,6 @@ namespace System.Text
m_ChunkLength = value - chunk.m_ChunkOffset;
AssertInvariants();
}
- Debug.Assert(Capacity >= originalCapacity);
}
}