Skip to content

Huge images cause negative allocation size error #2959

Description

@mfeemster

Prerequisites

  • I have written a descriptive issue title
  • I have verified that I am running the latest version of ImageSharp
  • I have verified if the problem exist in both DEBUG and RELEASE mode
  • I have searched open and closed issues to ensure it has not already been reported

ImageSharp version

Latest as of 6/25/2025

Other ImageSharp packages and versions

None

Environment (Operating system, version and so on)

Windows 10

.NET Framework version

.NET 9

Description

I am trying to decode this extremely large 14GB TIF file: https://rubinobservatory.org/gallery/collections/first-look-gallery/mlis3sriah6pn6nfr5ecp46h3i

and get an error: "Failed to allocate buffers for possibly degenerate dimensions: 0x0."

My machine has 64GB RAM and I set the buffer sizes to 40,000 (40GB) and it still happens.

From the stack trace below, it appears that when an image gets sufficiently large, the buffer sizes overflow and wrap to negative, thus throwing an exception. Possibly related to:

#2874

and also noted in:

#2870

try
{
	Configuration.Default.MemoryAllocator = MemoryAllocator.Create(new MemoryAllocatorOptions()
	{
		MaximumPoolSizeMegabytes = 20000,
		AllocationLimitMegabytes = 20000,
	});

	var filename = @"D:\Temp Downloads\Vera Rubin Cosmic Treasure Chest Im1.tif";
	var image = SixLabors.ImageSharp.Image.Load<Rgba32>(filename);
}
catch (Exception ex)
{
	Console.WriteLine(ex);
}

It threw an exception with this stack trace:

SixLabors.ImageSharp.InvalidImageContentException: Cannot decode image. Failed to allocate buffers for possibly degenerate dimensions: 0x0.
 ---> SixLabors.ImageSharp.Memory.InvalidMemoryOperationException: Attempted to allocate a buffer of negative length=-2037097840.
   at SixLabors.ImageSharp.Memory.InvalidMemoryOperationException.ThrowNegativeAllocationException(Int64 length) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Memory\InvalidMemoryOperationException.cs:line 32
   at SixLabors.ImageSharp.Memory.UniformUnmanagedMemoryPoolMemoryAllocator.Allocate[T](Int32 length, AllocationOptions options) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Memory\Allocators\UniformUnmanagedMemoryPoolMemoryAllocator.cs:line 88
   at SixLabors.ImageSharp.Formats.Tiff.TiffDecoderCore.DecodeStripsChunky[TPixel](ImageFrame`1 frame, Int32 width, Int32 height, Int32 rowsPerStrip, Span`1 stripOffsets, Span`1 stripByteCounts, CancellationToken cancellationToken) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Formats\Tiff\TiffDecoderCore.cs:line 513
   at SixLabors.ImageSharp.Formats.Tiff.TiffDecoderCore.DecodeImageWithStrips[TPixel](ExifProfile tags, ImageFrame`1 frame, Int32 width, Int32 height, CancellationToken cancellationToken) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Formats\Tiff\TiffDecoderCore.cs:line 339
   at SixLabors.ImageSharp.Formats.Tiff.TiffDecoderCore.DecodeFrame[TPixel](ExifProfile tags, Nullable`1 size, CancellationToken cancellationToken) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Formats\Tiff\TiffDecoderCore.cs:line 272
   at SixLabors.ImageSharp.Formats.Tiff.TiffDecoderCore.Decode[TPixel](BufferedReadStream stream, CancellationToken cancellationToken) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Formats\Tiff\TiffDecoderCore.cs:line 176
   at SixLabors.ImageSharp.Formats.ImageDecoderCore.Decode[TPixel](Configuration configuration, Stream stream, CancellationToken cancellationToken) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Formats\ImageDecoderCore.cs:line 82
   --- End of inner exception stack trace ---
   at SixLabors.ImageSharp.Formats.ImageDecoderCore.Decode[TPixel](Configuration configuration, Stream stream, CancellationToken cancellationToken) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Formats\ImageDecoderCore.cs:line 86
   at SixLabors.ImageSharp.Formats.Tiff.TiffDecoder.Decode[TPixel](DecoderOptions options, Stream stream, CancellationToken cancellationToken) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Formats\Tiff\TiffDecoder.cs:line 38
   at SixLabors.ImageSharp.Formats.ImageDecoder.<>c__DisplayClass0_0`1.<Decode>b__0(Stream s) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Formats\ImageDecoder.cs:line 24
   at SixLabors.ImageSharp.Formats.ImageDecoder.<WithSeekableStream>g__PerformActionAndResetPosition|11_0[T](Stream s, Int64 position, <>c__DisplayClass11_0`1&) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Formats\ImageDecoder.cs:line 201
   at SixLabors.ImageSharp.Formats.ImageDecoder.WithSeekableStream[T](DecoderOptions options, Stream stream, Func`2 action)
   at SixLabors.ImageSharp.Formats.ImageDecoder.Decode[TPixel](DecoderOptions options, Stream stream) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Formats\ImageDecoder.cs:line 21
   at SixLabors.ImageSharp.Image.Decode[TPixel](DecoderOptions options, Stream stream) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Image.Decode.cs:line 185
   at SixLabors.ImageSharp.Image.<>c__DisplayClass91_0`1.<Load>b__0(Stream s) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Image.FromStream.cs:line 234
   at SixLabors.ImageSharp.Image.WithSeekableStream[T](DecoderOptions options, Stream stream, Func`2 action) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Image.FromStream.cs:line 301
   at SixLabors.ImageSharp.Image.Load[TPixel](DecoderOptions options, Stream stream) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Image.FromStream.cs:line 234
   at SixLabors.ImageSharp.Image.Load[TPixel](DecoderOptions options, String path) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Image.FromFile.cs:line 254
   at SixLabors.ImageSharp.Image.Load[TPixel](String path) in D:\Dev\ImageSharpTest\ImageSharp\src\ImageSharp\Image.FromFile.cs:line 233
   at SixLabors.ImageSharp.Tests.ProfilingSandbox.Program.Main(String[] args) in D:\Dev\ImageSharpTest\ImageSharp\tests\ImageSharp.Tests.ProfilingSandbox\Program.cs:line 43

Steps to Reproduce

Download the file linked in the description.

Run the code in the description on a machine with sufficient RAM.

See the exception get thrown.

Images

No response

Activity

  1. aevitas commented on Jun 26, 2025

    @aevitas

    What dimensions is your image?

  2. mfeemster commented on Jun 26, 2025

    @mfeemster
    Author

    w: 97,943
    h: 51,536

    That comes out to 5,047,590,448 pixels which is larger than an uint can hold, so perhaps long should be used?

    It's a huge image, but my machine has enough memory to load it, so it should load. I think there is a bug with large image dimensions overflowing and becoming negative.

  3. aevitas commented on Jun 26, 2025

    @aevitas

    If I recall correctly, this runs into a limitation with ArrayPool<T> in that the maximum number of elements that can be rented is an int, while every pixel is RGBA, so four bytes. It's likely more of an issue with the allocation strategy, as was the case in the chunk decoder previously.

  4. JimBobSquarePants commented on Jun 26, 2025

    @JimBobSquarePants
    Member

    That’s exactly the issue. The code requires refactoring in the decoder to work per-row. I have a fix in mind already.

  5. mfeemster commented on Jul 30, 2025

    @mfeemster
    Author

    I'm looking to process some large images this winter and was wondering if any progress has been made on this issue and if there's a rough estimate of a completion date?

  6. JimBobSquarePants commented on Jul 30, 2025

    @JimBobSquarePants
    Member

    This is a deceptively tricky issue.

    While I can patch a workaround in v3 by checking for NoneTiffCompression, properly handling this in v4 requires a more comprehensive solution. The core problem is that there's no reliable way to know how many compressed bytes correspond to a single uncompressed row without maintaining decompression state or implementing more granular stream control. Because of that, it's difficult to estimate a completion date until I’ve explored and tested a robust design.

  7. mfeemster commented on Jul 30, 2025

    @mfeemster
    Author

    Thanks for the update, I appreciate it.

    I haven't looked at the code myself, but perhaps allow a user-specified option for max row size? Try to decompress in a try/catch block in a loop and steadily increase the buffer until either an exception is not thrown, or the user-specified limit is hit? Just a thought.

  8. added 2 commits that reference this issue on Oct 24, 2025
    91045ad
    c3e990f
  9. mfeemster commented on Oct 25, 2025

    @mfeemster
    Author

    I've confirmed this works with the huge Vera Rubin Telescope image sample I provided above. Thank you for fixing this and I'm looking forward to seeing it published on nuget. 👍

  10. JimBobSquarePants commented on Oct 29, 2025

    @JimBobSquarePants
    Member

    Thanks for testing @mfeemster

    I should be able to do a release in the next day or two.

  11. JimBobSquarePants commented on Oct 29, 2025

    @JimBobSquarePants
    Member

    Released!

  12. mfeemster commented on Oct 30, 2025

    @mfeemster
    Author

    I've tried rebuilding and running my project with the updated package and it still fails. Did the changes somehow not make it to the 3.1.12 release binary?

    If I build ImageSharp from source and put these lines in ImageSharp.Tests.ProfilingSandbox.Program.cs, it works fine:

    var filename = @"C:\Temp\Vera Rubin Cosmic Treasure Chest Im1.tif";
    var image = SixLabors.ImageSharp.Image.Load<Rgba32>(filename);
    

    However, the same lines in my project which uses the ImageSharp 3.1.12 dll via nuget package will fail. Both attempts target x64.

  13. JimBobSquarePants commented on Oct 30, 2025

    @JimBobSquarePants
    Member

    The changelog is here.

    https://github.com/SixLabors/ImageSharp/releases/tag/v3.1.12

    This is automatically generated from commits.

    Update

    Just tested using LINQpad, definitely working.

    Image
  14. mfeemster commented on Oct 30, 2025

    @mfeemster
    Author

    Disregard my comment. It was a very strange scenario where I was running on another machine with an older version of Powershell installed which was parsing my command line arguments incorrectly. Once I used the new Powershell, it worked fine. We're good now!

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions