diff --git a/src/Lucene.Net.Tests/Util/TestByteBlockPool.cs b/src/Lucene.Net.Tests/Util/TestByteBlockPool.cs index 522f894c87..4e70dd09a3 100644 --- a/src/Lucene.Net.Tests/Util/TestByteBlockPool.cs +++ b/src/Lucene.Net.Tests/Util/TestByteBlockPool.cs @@ -1,5 +1,7 @@ -using NUnit.Framework; +using Lucene.Net.Attributes; +using NUnit.Framework; using RandomizedTesting.Generators; +using System; using System.Collections.Generic; using JCG = J2N.Collections.Generic; using Assert = Lucene.Net.TestFramework.Assert; @@ -68,5 +70,54 @@ public virtual void TestReadAndWrite() } } } + + [Test] + [LuceneNetSpecific] // LUCENENET issue #1003 + public void TestTooManyAllocs() + { + // Use a mock allocator that doesn't waste memory + ByteBlockPool pool = new ByteBlockPool(new MockAllocator(0)); + pool.NextBuffer(); + + bool throwsException = false; + int maxIterations = int.MaxValue / ByteBlockPool.BYTE_BLOCK_SIZE + 1; + + for (int i = 0; i < maxIterations; i++) + { + try + { + pool.NextBuffer(); + } + catch (OverflowException) + { + // The offset overflows on the last attempt to call NextBuffer() + throwsException = true; + break; + } + } + + Assert.IsTrue(throwsException); + Assert.IsTrue(pool.ByteOffset + ByteBlockPool.BYTE_BLOCK_SIZE < pool.ByteOffset); + } + + private class MockAllocator : ByteBlockPool.Allocator + { + private readonly byte[] buffer; + + public MockAllocator(int blockSize) : base(blockSize) + { + buffer = Array.Empty(); + } + + public override void RecycleByteBlocks(byte[][] blocks, int start, int end) + { + // No-op + } + + public override byte[] GetByteBlock() + { + return buffer; + } + } } } diff --git a/src/Lucene.Net/Util/ByteBlockPool.cs b/src/Lucene.Net/Util/ByteBlockPool.cs index 898eaf077a..a2df7defb5 100644 --- a/src/Lucene.Net/Util/ByteBlockPool.cs +++ b/src/Lucene.Net/Util/ByteBlockPool.cs @@ -262,7 +262,11 @@ public void NextBuffer() bufferUpto++; ByteUpto = 0; - ByteOffset += BYTE_BLOCK_SIZE; + + checked // LUCENENET specific - added checked to prevent overflow, issue #1003 + { + ByteOffset += BYTE_BLOCK_SIZE; + } } ///