Fix corrupted StringBuilder state after out of memory exception
authorJan Kotas <jkotas@microsoft.com>
Wed, 31 Oct 2018 18:19:32 +0000 (11:19 -0700)
committerJan Kotas <jkotas@microsoft.com>
Thu, 1 Nov 2018 00:36:56 +0000 (17:36 -0700)
Fixes dotnet/coreclr#20718

Commit migrated from https://github.com/dotnet/coreclr/commit/92ea7612b2f33f2a69177846314be1d8ecfcf0cc

src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs

index 2e1b067..ef84d90 100644 (file)
@@ -2337,19 +2337,20 @@ namespace System.Text
             //     really big chunks even if the string gets really big.
             int newBlockLength = Math.Max(minBlockCharCount, Math.Min(Length, MaxChunkSize));
 
+            // Check for integer overflow (logical buffer size > int.MaxValue)
+            if (m_ChunkOffset + m_ChunkLength + newBlockLength < newBlockLength)
+                throw new OutOfMemoryException();
+
+            // Allocate the array before updating any state to avoid leaving inconsistent state behind in case of out of memory exception
+            char[] chunkChars = new char[newBlockLength];
+
             // Move all of the data from this chunk to a new one, via a few O(1) pointer adjustments.
             // Then, have this chunk point to the new one as its predecessor.
             m_ChunkPrevious = new StringBuilder(this);
             m_ChunkOffset += m_ChunkLength;
             m_ChunkLength = 0;
 
-            // Check for integer overflow (logical buffer size > int.MaxValue)
-            if (m_ChunkOffset + newBlockLength < newBlockLength)
-            {
-                m_ChunkChars = null;
-                throw new OutOfMemoryException();
-            }
-            m_ChunkChars = new char[newBlockLength];
+            m_ChunkChars = chunkChars;
 
             AssertInvariants();
         }