Skip to content

Commit f610923

Browse files
alinpahontu2912Copilotteo-tsirpanis
authored
Update MemoryStream max capacity (#119089)
* cap memory stream max length and add unit test for max capacity * Update src/libraries/System.Private.CoreLib/src/System/IO/MemoryStream.cs Co-authored-by: Copilot <[email protected]> * fix failing tests * Replace hardcoded value Co-authored-by: Theodore Tsirpanis <[email protected]> * update error message --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: Theodore Tsirpanis <[email protected]>
1 parent 7cff962 commit f610923

File tree

4 files changed

+31
-11
lines changed

4 files changed

+31
-11
lines changed

src/libraries/System.Private.CoreLib/src/Resources/Strings.resx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1944,7 +1944,7 @@
19441944
<value>startIndex cannot be larger than length of string.</value>
19451945
</data>
19461946
<data name="ArgumentOutOfRange_StreamLength" xml:space="preserve">
1947-
<value>Stream length must be non-negative and less than 2^31 - 1 - origin.</value>
1947+
<value>Stream length must be non-negative and less than the maximum array length (0x7FFFFFC7) - origin.</value>
19481948
</data>
19491949
<data name="ArgumentOutOfRange_UIntPtrMax" xml:space="preserve">
19501950
<value>The length of the buffer must be less than the maximum UIntPtr value for your platform.</value>

src/libraries/System.Private.CoreLib/src/System/IO/MemoryStream.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Buffers;
@@ -34,7 +34,7 @@ public class MemoryStream : Stream
3434

3535
private CachedCompletedInt32Task _lastReadTask; // The last successful task returned from ReadAsync
3636

37-
private const int MemStreamMaxLength = int.MaxValue;
37+
private static int MemStreamMaxLength => Array.MaxLength;
3838

3939
public MemoryStream()
4040
: this(0)
@@ -536,24 +536,24 @@ private long SeekCore(long offset, int loc)
536536

537537
// Sets the length of the stream to a given value. The new
538538
// value must be nonnegative and less than the space remaining in
539-
// the array, int.MaxValue - origin
539+
// the array, MemStreamMaxLength - origin
540540
// Origin is 0 in all cases other than a MemoryStream created on
541541
// top of an existing array and a specific starting offset was passed
542542
// into the MemoryStream constructor. The upper bounds prevents any
543543
// situations where a stream may be created on top of an array then
544544
// the stream is made longer than the maximum possible length of the
545-
// array (int.MaxValue).
545+
// array (MemStreamMaxLength).
546546
//
547547
public override void SetLength(long value)
548548
{
549-
if (value < 0 || value > int.MaxValue)
549+
if (value < 0 || value > MemStreamMaxLength)
550550
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_StreamLength);
551551

552552
EnsureWriteable();
553553

554554
// Origin wasn't publicly exposed above.
555-
Debug.Assert(MemStreamMaxLength == int.MaxValue); // Check parameter validation logic in this method if this fails.
556-
if (value > (int.MaxValue - _origin))
555+
Debug.Assert(MemStreamMaxLength == 0x7FFFFFC7); // Check parameter validation logic in this method if this fails.
556+
if (value > (MemStreamMaxLength - _origin))
557557
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_StreamLength);
558558

559559
int newLength = _origin + (int)value;

src/libraries/System.Runtime/tests/System.IO.Tests/BinaryWriter/BinaryWriterTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public void BinaryWriter_EncodingCtorAndWriteTests_Negative()
9191
[Fact]
9292
public void BinaryWriter_SeekTests()
9393
{
94-
int[] iArrLargeValues = new int[] { 10000, 100000, int.MaxValue / 200, int.MaxValue / 1000, short.MaxValue, int.MaxValue, int.MaxValue - 1, int.MaxValue / 2, int.MaxValue / 10, int.MaxValue / 100 };
94+
int[] iArrLargeValues = new int[] { 10000, 100000, int.MaxValue / 200, int.MaxValue / 1000, short.MaxValue, Array.MaxLength, Array.MaxLength - 1, int.MaxValue / 2, int.MaxValue / 10, int.MaxValue / 100 };
9595

9696
BinaryWriter dw2 = null;
9797
MemoryStream mstr = null;

src/libraries/System.Runtime/tests/System.IO.Tests/MemoryStream/MemoryStreamTests.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ public void MemoryStream_SeekOverflow_Throws(SeekMode mode, int bufferSize, int
105105
byte[] buffer = new byte[bufferSize];
106106
using (MemoryStream ms = new MemoryStream(buffer, origin, buffer.Length - origin, true))
107107
{
108-
Seek(mode, ms, int.MaxValue - origin);
109-
Assert.Throws<ArgumentOutOfRangeException>(() => Seek(mode, ms, (long)int.MaxValue - origin + 1));
108+
Seek(mode, ms, Array.MaxLength - origin);
109+
Assert.Throws<ArgumentOutOfRangeException>(() => Seek(mode, ms, (long)Array.MaxLength - origin + 1));
110110
Assert.ThrowsAny<Exception>(() => Seek(mode, ms, long.MinValue + 1));
111111
Assert.ThrowsAny<Exception>(() => Seek(mode, ms, long.MaxValue - 1));
112112
}
@@ -146,6 +146,26 @@ public async Task DerivedMemoryStream_ReadWriteAsyncMemoryCalled_ReadWriteAsyncA
146146
Assert.True(s.ReadArrayInvoked);
147147
}
148148

149+
[Fact]
150+
[SkipOnCI("Skipping on CI due to large memory allocation")]
151+
public void MemoryStream_CapacityBoundaryChecks()
152+
{
153+
int MaxSupportedLength = Array.MaxLength;
154+
155+
using (var ms = new MemoryStream())
156+
{
157+
ms.Capacity = MaxSupportedLength - 1;
158+
Assert.Equal(MaxSupportedLength - 1, ms.Capacity);
159+
160+
ms.Capacity = MaxSupportedLength;
161+
Assert.Equal(MaxSupportedLength, ms.Capacity);
162+
163+
Assert.Throws<ArgumentOutOfRangeException>(() => ms.Capacity = MaxSupportedLength + 1);
164+
165+
Assert.Throws<ArgumentOutOfRangeException>(() => ms.Capacity = int.MaxValue);
166+
}
167+
}
168+
149169
private class ReadWriteOverridingMemoryStream : MemoryStream
150170
{
151171
public bool ReadArrayInvoked, WriteArrayInvoked;

0 commit comments

Comments
 (0)