From 5b0ce2dd4038d8978f9be6baff38b7ef70caaff8 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 22 Jul 2021 14:14:07 -0700 Subject: [PATCH] Fix overflow error in ReturnBlocks (#187) * Fix overflow error in ReturnBlocks * Check for underflow/overflow in debug builds Co-authored-by: Ben Watson --- UnitTests/Tests.cs | 29 +++++++++++++++++++ UnitTests/UnitTests.csproj | 1 + ...Microsoft.IO.RecyclableMemoryStream.csproj | 1 + src/RecyclableMemoryStreamManager.cs | 2 +- 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/UnitTests/Tests.cs b/UnitTests/Tests.cs index a6729cf1..64dd1092 100644 --- a/UnitTests/Tests.cs +++ b/UnitTests/Tests.cs @@ -3384,6 +3384,35 @@ private RecyclableMemoryStream GetRandomStream() } #endregion + #region Bug Reports + // Issue #176 - SmallPoolInUseSize, SmallPoolFreeSize + [Test] + public void Issue176_PoolInUseSizeDoesNotDecrease() + { + long maximumFreeSmallPoolBytes = 32000L * 128000; //4096000000 + long maximumFreeLargePoolBytes = UInt32.MaxValue; + int blockSize = 128000; + + var mgr = new RecyclableMemoryStreamManager(blockSize, 1<<20, 8 * (1<<20), + maximumFreeSmallPoolBytes, maximumFreeLargePoolBytes); + + MemoryStream fillStream = mgr.GetStream("pool", requiredSize: 128000, asContiguousBuffer: true); + byte[] block1 = new byte[128000]; + long test1 = 4096000000; + int test2 = 128000; + for (int i = 0; i < 32000; i++) + { + fillStream.Write(block1, 0, 128000); + test1 -= test2; + } + + Assert.That(test1, Is.EqualTo(0)); + Assert.That(mgr.SmallPoolInUseSize, Is.EqualTo(maximumFreeSmallPoolBytes)); + fillStream.Dispose(); + Assert.That(mgr.SmallPoolInUseSize, Is.EqualTo(0)); + } + #endregion + protected abstract bool AggressiveBufferRelease { get; } protected virtual bool UseExponentialLargeBuffer diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index ec11a7ff..548f8d9d 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -3,6 +3,7 @@ Microsoft.IO.RecyclableMemoryStream.UnitTests net5.0 Full + true diff --git a/src/Microsoft.IO.RecyclableMemoryStream.csproj b/src/Microsoft.IO.RecyclableMemoryStream.csproj index 53f9a450..bdc5111d 100644 --- a/src/Microsoft.IO.RecyclableMemoryStream.csproj +++ b/src/Microsoft.IO.RecyclableMemoryStream.csproj @@ -21,6 +21,7 @@ https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStream true 9.0 + true diff --git a/src/RecyclableMemoryStreamManager.cs b/src/RecyclableMemoryStreamManager.cs index 219bc137..f3725846 100644 --- a/src/RecyclableMemoryStreamManager.cs +++ b/src/RecyclableMemoryStreamManager.cs @@ -562,7 +562,7 @@ internal void ReturnBlocks(ICollection blocks, Guid id, string tag) throw new ArgumentNullException(nameof(blocks)); } - var bytesToReturn = blocks.Count * this.BlockSize; + long bytesToReturn = (long)blocks.Count * (long)this.BlockSize; Interlocked.Add(ref this.smallPoolInUseSize, -bytesToReturn); foreach (var block in blocks)