Skip to content

PNG decoder: buffer allocated in ReadChunkData is not disposed when the read is cancelled #3202

Description

@HishamMalik-iQNOS

Prerequisites

Checks and verification limits:

  • I have written a descriptive issue title
  • I have verified that I am running the latest version of ImageSharp — 4.1.2, checked on 2026-10-04
  • I have verified if the problem exist in both DEBUG and RELEASE mode — only a Release build of the repro was run
  • I have searched open and closed issues — relevant ReadChunkData and cancellation/memory searches found no matching report.

ImageSharp version

4.1.2 (4.1.2+dee414097e4be7bb35ef0209cf96bd0b61a7133a)

Other ImageSharp packages and versions

None.

Environment (Operating system, version and so on)

Windows x64 (Microsoft Windows 10.0.26300).

.NET Framework version

.NET 10.0.12.

Description

When a PNG Identify or Decode is cancelled, the buffer that
PngDecoderCore.ReadChunkData rents from the configured MemoryAllocator can
be left undisposed.

ReadChunkData allocates the chunk buffer and then reads into it through
BufferedReadStream. That read begins with
CancellationToken.ThrowIfCancellationRequested(). If cancellation is observed
there, the exception leaves ReadChunkData before the buffer is returned, so
nothing ever disposes it. The callers dispose chunk data in a finally
(chunk.Data?.Dispose()), but that block only wraps the body of the
while (this.TryReadChunk(...)) loop. It never sees a buffer whose
TryReadChunk call threw.

The effect: MemoryDiagnostics.TotalUndisposedAllocationCount stays one above
its baseline after the cancelled operation. After the processing method returns
and the reproduction performs diagnostic GC, the library's
UndisposedAllocation event reports an undisposed buffer, with an allocation
stack in PngDecoderCore.TryReadChunk. The first-chance throw stack also
includes ReadChunkData.

This demonstrates missing explicit disposal, not that the memory necessarily
remains allocated forever after finalization. The diagnostic count does not
decrement on finalization. Only Release was run; Debug remains unverified.

Source at the v4.1.2 commit:

From the source, not exercised by the repro: in 4.1.2 TryReadChunk also
calls ReadChunkData for IDAT/fdAT chunks (it reads them to check the CRC),
so the same window exists for data chunks. The repro cancels at the first such
allocation in each phase.

How we found it: a test that cancels processing after 0, 5, 20 and 60 ms and
then asserts TotalUndisposedAllocationCount is back to its baseline failed
intermittently (expected 0, actual 1). The inline repro below makes that window
deterministic. It shows the mechanism; it does not show that every
intermittent failure we saw took this path.

Expected: the buffer is released on every path, including cancellation, so
the undisposed count returns to its baseline.

Steps to Reproduce

The inline repro below is a console app that references only ImageSharp 4.1.2 and
generates its own 2048×1536 PNG. Save the two files below into a repro
directory. Building requires the .NET 10 SDK and the normal ImageSharp 4 license
configuration; no license key is included. Run one case per process:

cd repro
dotnet build -c Release
dotnet run -c Release --no-build -- A   # no cancellation
dotnet run -c Release --no-build -- B   # token cancelled before the operation
dotnet run -c Release --no-build -- C   # cancelled at the ReadChunkData allocation in Identify
dotnet run -c Release --no-build -- D   # cancelled at the ReadChunkData allocation in Decode

To make the timing deterministic, the repro observes the internal
MemoryDiagnostics.MemoryAllocated event through reflection (diagnostics only,
nothing is patched). It cancels the token once, from inside the allocation
whose stack contains PngDecoderCore.ReadChunkData in the chosen phase, so the
next statement — the stream read — throws.

Result of one run per case:

Case Outcome Undisposed count, before any GC Finalizer reports
A completed (2048×1536) +0 0
B TaskCanceledException +0 0
C TaskCanceledException +1 1
D TaskCanceledException +1 1

Throw site in C (D is the same under Decode):

at System.Threading.CancellationToken.ThrowIfCancellationRequested
at SixLabors.ImageSharp.IO.BufferedReadStream.Read
at SixLabors.ImageSharp.BufferedReadStreamExtensions.Read
at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.ReadChunkData
at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.TryReadChunk
at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.Identify

Images

None needed: the repro generates its input.

Complete reproduction

repro/PngCancellationLeakRepro.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="SixLabors.ImageSharp" Version="4.1.2" />
  </ItemGroup>

</Project>
repro/Program.cs
// Minimal reproduction for SixLabors.ImageSharp 4.1.2: the buffer rented in
// PngDecoderCore.ReadChunkData is never disposed when the stream read that
// follows the allocation observes cancellation.
//
// The cancellation is made deterministic by cancelling from inside that
// allocation. The internal MemoryDiagnostics.MemoryAllocated event is observed
// through reflection (diagnostics only; nothing in ImageSharp is patched). On
// each allocation the stack is checked for PngDecoderCore.ReadChunkData inside
// the intended phase (Identify or Decode), and the token is cancelled once. The
// next statement in ReadChunkData is the BufferedReadStream read, which throws.
//
// Usage, one case per process:
//   dotnet run -c Release -- A    no cancellation
//   dotnet run -c Release -- B    token cancelled before the operation starts
//   dotnet run -c Release -- C    cancelled at the ReadChunkData allocation in Identify
//   dotnet run -c Release -- D    cancelled at the ReadChunkData allocation in Decode

using System.Collections.Concurrent;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Diagnostics;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;

var caseId = args.Length == 1 ? args[0].ToUpperInvariant() : string.Empty;
if (caseId is not ("A" or "B" or "C" or "D"))
{
    Console.Error.WriteLine("usage: dotnet run -c Release -- A|B|C|D");
    return 2;
}

Out("case", caseId switch
{
    "A" => "A - no cancellation",
    "B" => "B - token cancelled before the operation starts",
    "C" => "C - cancelled at the ReadChunkData allocation in PNG Identify",
    _ => "D - cancelled at the ReadChunkData allocation in PNG Decode"
});
Out("runtime", RuntimeInformation.FrameworkDescription);
Out("os", RuntimeInformation.OSDescription);
Out("arch", RuntimeInformation.ProcessArchitecture);
Out("imagesharp", typeof(Image).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion);

var memoryAllocated = typeof(MemoryDiagnostics).GetEvent(
    "MemoryAllocated",
    BindingFlags.NonPublic | BindingFlags.Static);
if (memoryAllocated is null)
{
    Out("result", "cannot run: internal MemoryDiagnostics.MemoryAllocated not found");
    return 3;
}

// Input: a plain 2048x1536 RGBA PNG generated here; no external file.
var png = CreatePng(2048, 1536);
Out("input", $"generated PNG 2048x1536, {png.Length} bytes");

// Settle before taking the baseline.
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

// The library's own finalizer-based report of undisposed allocations. Subscribing
// also makes it record an allocation stack for each allocation from here on.
var undisposedReports = new ConcurrentQueue<string>();
MemoryDiagnostics.UndisposedAllocation += stack => undisposedReports.Enqueue(stack);

var baseline = MemoryDiagnostics.TotalUndisposedAllocationCount;
Out("baseline.TotalUndisposedAllocationCount", baseline);

using var cancellation = new CancellationTokenSource();
var targetPhase = caseId switch { "C" => "Identify", "D" => "Decode", _ => null };
var otherPhase = caseId switch { "C" => "Decode", "D" => "Identify", _ => null };
var fired = 0;
string? hookStack = null;

var onAllocated = new Action(() =>
{
    if (targetPhase is null || Volatile.Read(ref fired) != 0)
    {
        return;
    }

    var frames = new StackTrace(fNeedFileInfo: false).GetFrames();
    bool inReadChunkData = false, inTarget = false, inOther = false;

    foreach (var frame in frames)
    {
        var method = frame.GetMethod();
        if (method?.DeclaringType?.Name != "PngDecoderCore")
        {
            continue;
        }

        if (method.Name == "ReadChunkData")
        {
            inReadChunkData = true;
        }
        else if (method.Name == targetPhase)
        {
            inTarget = true;
        }
        else if (method.Name == otherPhase)
        {
            inOther = true;
        }
    }

    if (!inReadChunkData || !inTarget || inOther || Interlocked.CompareExchange(ref fired, 1, 0) != 0)
    {
        return;
    }

    hookStack = Frames(frames.Skip(1), 10);

    // The allocation has happened; the read that follows it has not.
    cancellation.Cancel();
});

// The stack at the point where the cancellation is thrown (an awaited
// exception no longer carries it).
string? throwSite = null;
AppDomain.CurrentDomain.FirstChanceException += (_, e) =>
{
    if (e.Exception is OperationCanceledException && throwSite is null)
    {
        // From the token's throw helper when there is one; otherwise from the
        // first frame after this handler and the runtime's dispatch.
        var frames = new StackTrace(fNeedFileInfo: false).GetFrames().Skip(1).ToArray();
        var fromToken = frames.SkipWhile(f =>
            f.GetMethod()?.DeclaringType?.FullName?.StartsWith("System.Threading.CancellationToken", StringComparison.Ordinal) != true).ToArray();
        throwSite = Frames(
            fromToken.Length > 0
                ? fromToken
                : frames.SkipWhile(f => f.GetMethod()?.DeclaringType?.FullName?.StartsWith("System.Runtime.EH", StringComparison.Ordinal) == true),
            8);
    }
};

if (targetPhase is not null)
{
    memoryAllocated.GetAddMethod(nonPublic: true)!.Invoke(null, [onAllocated]);
}

if (caseId == "B")
{
    cancellation.Cancel();
}

var (outcome, awaitStack, immediate) = await RunAsync(png, cancellation.Token);

if (targetPhase is not null)
{
    memoryAllocated.GetRemoveMethod(nonPublic: true)!.Invoke(null, [onAllocated]);
}

Out("trigger", targetPhase is null
    ? "n/a"
    : fired == 1
        ? $"fired once, at the ReadChunkData allocation inside PngDecoderCore.{targetPhase}"
        : "DID NOT FIRE - the intended allocation was not identified, so this run shows nothing");
if (hookStack is not null)
{
    Console.WriteLine("trigger.allocationStack=" + Environment.NewLine + hookStack);
}

Out("outcome", outcome);
if (awaitStack is not null)
{
    Console.WriteLine("outcome.awaitStack=" + Environment.NewLine + awaitStack);
}

Console.WriteLine("cancellation.throwSite=" + (throwSite is null ? "none" : Environment.NewLine + throwSite));
Out("immediate.TotalUndisposedAllocationCount", immediate);
Out("immediate.delta", immediate - baseline);

// Diagnostic only, after the measurement above: once the configuration that
// owns the allocator is unreachable, lets the library's finalizer report any
// allocation that was never disposed.
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
Out("afterGc.TotalUndisposedAllocationCount.delta", MemoryDiagnostics.TotalUndisposedAllocationCount - baseline);
Out("undisposedAllocationReports", undisposedReports.Count);

var index = 0;
foreach (var report in undisposedReports)
{
    index++;
    var lines = report
        .Split('\n')
        .Select(line => Regex.Replace(line.TrimEnd('\r'), @" in .+?:line \d+$", string.Empty))
        .Where(line => line.Contains(" at ", StringComparison.Ordinal))
        .Take(9);
    Console.WriteLine($"undisposedAllocationReport[{index}].allocationStack=" + Environment.NewLine + string.Join(Environment.NewLine, lines));
}

return 0;

// Identify, then decode, with a dedicated configuration that is unreachable once
// this returns. The undisposed count is read here, before any GC.
[MethodImpl(MethodImplOptions.NoInlining)]
static async Task<(string Outcome, string? AwaitStack, int Immediate)> RunAsync(byte[] png, CancellationToken token)
{
    var configuration = new Configuration(new PngConfigurationModule())
    {
        MemoryAllocator = MemoryAllocator.Create()
    };
    var options = new DecoderOptions { Configuration = configuration };

    string outcome;
    string? awaitStack = null;

    try
    {
        using var stream = new MemoryStream(png, writable: false);
        var info = await Image.IdentifyAsync(options, stream, token);

        stream.Position = 0;
        using var image = await Image.LoadAsync<Rgba32>(options, stream, token);

        outcome = $"completed: identified {info.Width}x{info.Height}, decoded {image.Width}x{image.Height}";
    }
    catch (Exception e)
    {
        outcome = $"{e.GetType().FullName}: {e.Message}";
        awaitStack = Frames(new StackTrace(e, fNeedFileInfo: false).GetFrames(), 6);
    }

    var immediate = MemoryDiagnostics.TotalUndisposedAllocationCount;
    GC.KeepAlive(configuration);

    return (outcome, awaitStack, immediate);
}

static byte[] CreatePng(int width, int height)
{
    using var image = new Image<Rgba32>(width, height);
    image.ProcessPixelRows(accessor =>
    {
        for (var y = 0; y < accessor.Height; y++)
        {
            var row = accessor.GetRowSpan(y);
            for (var x = 0; x < row.Length; x++)
            {
                row[x] = new Rgba32((byte)(x * 255 / width), (byte)(y * 255 / height), (byte)((x + y) & 0xFF), 255);
            }
        }
    });

    using var output = new MemoryStream();
    image.SaveAsPng(output);
    return output.ToArray();
}

static string Frames(IEnumerable<StackFrame> frames, int take)
{
    return string.Join(Environment.NewLine, frames.Take(take).Select(frame =>
    {
        var method = frame.GetMethod();
        return $"    at {method?.DeclaringType?.FullName}.{method?.Name}";
    }));
}

static void Out(string key, object? value) => Console.WriteLine($"{key}={value}");

Recorded output

These are the supplied Windows Release run outputs, one fresh process per case.

Case A
case=A - no cancellation
runtime=.NET 10.0.12
os=Microsoft Windows 10.0.26300
arch=X64
imagesharp=4.1.2+dee414097e4be7bb35ef0209cf96bd0b61a7133a
input=generated PNG 2048x1536, 16856 bytes
baseline.TotalUndisposedAllocationCount=0
trigger=n/a
outcome=completed: identified 2048x1536, decoded 2048x1536
cancellation.throwSite=none
immediate.TotalUndisposedAllocationCount=0
immediate.delta=0
afterGc.TotalUndisposedAllocationCount.delta=0
undisposedAllocationReports=0
Case B
case=B - token cancelled before the operation starts
runtime=.NET 10.0.12
os=Microsoft Windows 10.0.26300
arch=X64
imagesharp=4.1.2+dee414097e4be7bb35ef0209cf96bd0b61a7133a
input=generated PNG 2048x1536, 16856 bytes
baseline.TotalUndisposedAllocationCount=0
trigger=n/a
outcome=System.Threading.Tasks.TaskCanceledException: A task was canceled.
outcome.awaitStack=
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
    at System.Threading.Tasks.ValueTask`1.get_Result
    at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult
    at SixLabors.ImageSharp.Image+<InternalDetectFormatAsync>d__44.MoveNext
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
cancellation.throwSite=
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
    at System.Threading.Tasks.ValueTask`1.get_Result
    at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult
    at SixLabors.ImageSharp.Image+<InternalDetectFormatAsync>d__44.MoveNext
    at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start
    at System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1.Start
    at SixLabors.ImageSharp.Image.InternalDetectFormatAsync
immediate.TotalUndisposedAllocationCount=0
immediate.delta=0
afterGc.TotalUndisposedAllocationCount.delta=0
undisposedAllocationReports=0
Case C
case=C - cancelled at the ReadChunkData allocation in PNG Identify
runtime=.NET 10.0.12
os=Microsoft Windows 10.0.26300
arch=X64
imagesharp=4.1.2+dee414097e4be7bb35ef0209cf96bd0b61a7133a
input=generated PNG 2048x1536, 16856 bytes
baseline.TotalUndisposedAllocationCount=0
trigger=fired once, at the ReadChunkData allocation inside PngDecoderCore.Identify
trigger.allocationStack=
    at SixLabors.ImageSharp.Diagnostics.MemoryDiagnostics.IncrementTotalUndisposedAllocationCount
    at SixLabors.ImageSharp.Memory.Internals.RefCountedMemoryLifetimeGuard..ctor
    at SixLabors.ImageSharp.Memory.Internals.SharedArrayPoolBuffer`1+LifetimeGuard..ctor
    at SixLabors.ImageSharp.Memory.Internals.SharedArrayPoolBuffer`1..ctor
    at SixLabors.ImageSharp.Memory.UniformUnmanagedMemoryPoolMemoryAllocator.AllocateCore
    at SixLabors.ImageSharp.Memory.MemoryAllocator.Allocate
    at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.ReadChunkData
    at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.TryReadChunk
    at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.Identify
    at SixLabors.ImageSharp.Formats.ImageDecoderCore.Identify
outcome=System.Threading.Tasks.TaskCanceledException: A task was canceled.
outcome.awaitStack=
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
    at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter.GetResult
    at SixLabors.ImageSharp.Formats.ImageDecoder+<IdentifyAsync>d__5.MoveNext
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
cancellation.throwSite=
    at System.Threading.CancellationToken.ThrowOperationCanceledException
    at System.Threading.CancellationToken.ThrowIfCancellationRequested
    at SixLabors.ImageSharp.IO.BufferedReadStream.Read
    at SixLabors.ImageSharp.BufferedReadStreamExtensions.Read
    at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.ReadChunkData
    at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.TryReadChunk
    at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.Identify
    at SixLabors.ImageSharp.Formats.ImageDecoderCore.Identify
immediate.TotalUndisposedAllocationCount=1
immediate.delta=1
afterGc.TotalUndisposedAllocationCount.delta=1
undisposedAllocationReports=1
undisposedAllocationReport[1].allocationStack=
   at System.Environment.get_StackTrace()
   at SixLabors.ImageSharp.Memory.Internals.RefCountedMemoryLifetimeGuard..ctor()
   at SixLabors.ImageSharp.Memory.Internals.SharedArrayPoolBuffer`1.LifetimeGuard..ctor(Byte[] array)
   at SixLabors.ImageSharp.Memory.Internals.SharedArrayPoolBuffer`1..ctor(Int32 lengthInElements)
   at SixLabors.ImageSharp.Memory.UniformUnmanagedMemoryPoolMemoryAllocator.AllocateCore[T](Int32 length, AllocationOptions options)
   at SixLabors.ImageSharp.Memory.MemoryAllocator.Allocate[T](Int32 length, AllocationOptions options)
   at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.TryReadChunk(Span`1 buffer, PngChunk& chunk)
   at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.Identify(BufferedReadStream stream, CancellationToken cancellationToken)
   at SixLabors.ImageSharp.Formats.ImageDecoderCore.Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken)
Case D
case=D - cancelled at the ReadChunkData allocation in PNG Decode
runtime=.NET 10.0.12
os=Microsoft Windows 10.0.26300
arch=X64
imagesharp=4.1.2+dee414097e4be7bb35ef0209cf96bd0b61a7133a
input=generated PNG 2048x1536, 16856 bytes
baseline.TotalUndisposedAllocationCount=0
trigger=fired once, at the ReadChunkData allocation inside PngDecoderCore.Decode
trigger.allocationStack=
    at SixLabors.ImageSharp.Diagnostics.MemoryDiagnostics.IncrementTotalUndisposedAllocationCount
    at SixLabors.ImageSharp.Memory.Internals.RefCountedMemoryLifetimeGuard..ctor
    at SixLabors.ImageSharp.Memory.Internals.SharedArrayPoolBuffer`1+LifetimeGuard..ctor
    at SixLabors.ImageSharp.Memory.Internals.SharedArrayPoolBuffer`1..ctor
    at SixLabors.ImageSharp.Memory.UniformUnmanagedMemoryPoolMemoryAllocator.AllocateCore
    at SixLabors.ImageSharp.Memory.MemoryAllocator.Allocate
    at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.ReadChunkData
    at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.TryReadChunk
    at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.Decode
    at SixLabors.ImageSharp.Formats.ImageDecoderCore.Decode
outcome=System.Threading.Tasks.TaskCanceledException: A task was canceled.
outcome.awaitStack=
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
    at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter.GetResult
    at SixLabors.ImageSharp.Formats.ImageDecoder+<DecodeAsync>d__2`1.MoveNext
    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
cancellation.throwSite=
    at System.Threading.CancellationToken.ThrowOperationCanceledException
    at System.Threading.CancellationToken.ThrowIfCancellationRequested
    at SixLabors.ImageSharp.IO.BufferedReadStream.Read
    at SixLabors.ImageSharp.BufferedReadStreamExtensions.Read
    at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.ReadChunkData
    at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.TryReadChunk
    at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.Decode
    at SixLabors.ImageSharp.Formats.ImageDecoderCore.Decode
immediate.TotalUndisposedAllocationCount=1
immediate.delta=1
afterGc.TotalUndisposedAllocationCount.delta=1
undisposedAllocationReports=1
undisposedAllocationReport[1].allocationStack=
   at System.Environment.get_StackTrace()
   at SixLabors.ImageSharp.Memory.Internals.RefCountedMemoryLifetimeGuard..ctor()
   at SixLabors.ImageSharp.Memory.Internals.SharedArrayPoolBuffer`1.LifetimeGuard..ctor(Byte[] array)
   at SixLabors.ImageSharp.Memory.Internals.SharedArrayPoolBuffer`1..ctor(Int32 lengthInElements)
   at SixLabors.ImageSharp.Memory.UniformUnmanagedMemoryPoolMemoryAllocator.AllocateCore[T](Int32 length, AllocationOptions options)
   at SixLabors.ImageSharp.Memory.MemoryAllocator.Allocate[T](Int32 length, AllocationOptions options)
   at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.TryReadChunk(Span`1 buffer, PngChunk& chunk)
   at SixLabors.ImageSharp.Formats.Png.PngDecoderCore.Decode[TPixel](BufferedReadStream stream, CancellationToken cancellationToken)
   at SixLabors.ImageSharp.Formats.ImageDecoderCore.Decode[TPixel](Configuration configuration, Stream stream, CancellationToken cancellationToken)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions