Skip to content

Commit

Permalink
Fix Issue 344 by resolving infinite loop with buffers longer than Max…
Browse files Browse the repository at this point in the history
…ArrayLength.
  • Loading branch information
Ben Watson committed Jun 6, 2024
1 parent 5c59e93 commit 5e16378
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 3 deletions.
18 changes: 18 additions & 0 deletions UnitTests/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4057,7 +4057,25 @@ protected override void TestDroppingLargeBuffer(long maxFreeLargeBufferSize)
}
}
}
#pragma warning disable 618 // Timeout is obsolete because it kills the thread, which isn't allowed, but it's still handy
// for tests that are expected to run indefinitely in the failure case.
[Test, Timeout(10000)]
public void TryGetBuffer_InfiniteLoop_Issue344()
{
// see https://github.com/microsoft/Microsoft.IO.RecyclableMemoryStream/issues/344
var memMgr = this.GetMemoryManager();
var size = 1073741825; // this will cause infinite loop in TryGetBuffer below, 1073741824 works.
var bytes = new byte[size];
using (var ms = memMgr.GetStream())
{
ms.Write(bytes, 0, size);
bool result = ms.TryGetBuffer(out var segment);
Assert.That(result, Is.False);
Assert.That(segment, Is.Empty);
}
}
}
#pragma warning restore 618

[TestFixture]
public sealed class RecyclableMemoryStreamTestsWithPassiveBufferReleaseUsingExponentialLargeBuffer : BaseRecyclableMemoryStreamTestsUsingExponentialLargeBuffer
Expand Down
1 change: 1 addition & 0 deletions src/RecyclableMemoryStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ public override long Position
/// until <see cref="Dispose(bool)"/> is called, but the next time <c>GetBuffer</c> is called, a new buffer from the pool will be required.</remarks>
/// <exception cref="ObjectDisposedException">Object has been disposed.</exception>
/// <exception cref="OutOfMemoryException">stream is too large for a contiguous buffer.</exception>
/// <exception cref="OverflowException">stream is too long for a contiguous buffer.</exception>
public override byte[] GetBuffer()
{
this.CheckDisposed();
Expand Down
6 changes: 3 additions & 3 deletions src/RecyclableMemoryStreamManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -378,13 +378,13 @@ internal byte[] GetBlock()
/// <exception cref="OutOfMemoryException">Requested array size is larger than the maximum allowed.</exception>
internal byte[] GetLargeBuffer(long requiredSize, Guid id, string? tag)
{
requiredSize = this.RoundToLargeBufferSize(requiredSize);

if (requiredSize > MaxArrayLength)
{
throw new OutOfMemoryException($"Requested size exceeds maximum array length of {MaxArrayLength}.");
throw new OutOfMemoryException($"Required buffer size exceeds maximum array length of {MaxArrayLength}.");
}

requiredSize = this.RoundToLargeBufferSize(requiredSize);

var poolIndex = this.GetPoolIndex(requiredSize);

bool createdNew = false;
Expand Down

0 comments on commit 5e16378

Please sign in to comment.