Open CoderNate opened 2 years ago
I can consistently reproduce this in .NET framework 4.8 with the code below running as a console app. It doesn't appear to happen in .NET core 3.1.
class Program
{
static void Main(string[] args)
{
Console.WriteLine(System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription);
for (var i = 0; i < 20; i++)
{
RunTest();
}
}
static void RunTest()
{
using var ms = new System.IO.MemoryStream();
using var writer = Amazon.IonDotnet.Builders.IonBinaryWriterBuilder.Build(ms);
var r = new Random(0); // Always use the same seed so we get the same sequence of values out
writer.StepIn(Amazon.IonDotnet.IonType.List);
for (var i = 0; i < 100_000; i++)
{
var strLen = r.Next(10, 40);
try
{
writer.WriteString(new string('a', strLen));
}
catch (ArgumentOutOfRangeException ex)
{
Console.WriteLine($"Exception on i == {i}");
return;
}
}
}
}
This produces:
.NET Framework 4.8.4510.0
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
Exception on i == 979
I got this same result on a second machine running .NET 4.8.4110.0. I don't know if this could reliably be made into a unit test though because the bug is triggered by using the ArrayPool
that's shared by all threads.
The related fix has been merged; keeping this open so we can consider adding repeatable tests for this case.
I'm getting the following error:
In the constructor the
blockSize
gets set like this:Note that the
ArrayPool
can return a larger array than what you ask for. Later oncurrentBlock
gets replaced inAllocateNewBlock
:What I'm running into is:
blockSize
is set to 512 in the constructor andcurrentBlock
starts out having length 512AllocateNewBlock
theArrayPool
returns a block that's 1024 and it's assigned tocurrentBlock
WriteUtf8
method writes bytes as long as it doesn't go pastthis.currentBlock.Length
which is 1024WriteBytes
method looks atblockSize
instead ofcurrentBlock.Length
:I assume that
WriteBytes
should refer tocurrentBlock.Length
like all the other methods do instead ofblockSize
. Perhaps theblockSize
field should be removed. However,AllocateNewBlock
needs to know what size to pass toArrayPool.Rent
so maybe theintendedBlockSize
argument from the constructor should be stored in a readonly field for that purpose in place of usingblockSize
.Thanks for making this library available!