Skip to content

Exception in LzwString.WriteTo when attempting to load a TIFF image #2983

@brianberns

Description

@brianberns

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

3.1.11

Other ImageSharp packages and versions

None

Environment (Operating system, version and so on)

Windows 11

.NET Framework version

.NET 8

Description

While attempting to load a TIFF image found in the wild, an IndexOutOfRangeException occurs on line 87 in LzwString.WriteTo:

    public int WriteTo(Span<byte> buffer, int offset)
    {
        if (this.Length == 0)
        {
            return 0;
        }

        if (this.Length == 1)
        {
            buffer[offset] = this.value;
            return 1;
        }

        LzwString e = this;
        int endIdx = this.Length - 1;
        if (endIdx >= buffer.Length)
        {
            TiffThrowHelper.ThrowImageFormatException("Error reading lzw compressed stream. Either pixel buffer to write to is to small or code length is invalid!");
        }

        for (int i = endIdx; i >= 0; i--)
        {
            buffer[offset + i] = e.value;   // <==== EXCEPTION OCCURS HERE ****
            e = e.previous;
        }

        return this.Length;
    }

At this point, buffer has a length of 7808, offset is 7750, and i is 58. Since 7750+58 = 7808, the attempt to write to the buffer is out of range. There appears to be an attempt to test for such an overflow a few lines above (if (endIdx >= buffer.Length)), but it does not take the offset into account.

The image opens successfully in other tools, such as the Windows Photo app and Photoshop Elements.

I noticed a very similar problem described in a closed issue, but this is either a different problem, or the original problem was not actually fixed.

Steps to Reproduce

I'm attempting to get permission to share the TIFF image file. In the meantime, here is the stack trace:

 	System.Private.CoreLib.dll!System.ThrowHelper.ThrowIndexOutOfRangeException()	Unknown
 	System.Private.CoreLib.dll!System.Span<byte>.this[int].get(int index)	Unknown
>	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors.LzwString.WriteTo(System.Span<byte> buffer, int offset) Line 87	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors.TiffLzwDecoder.DecodePixels(System.Span<byte> pixels) Line 161	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors.LzwTiffCompression.Decompress(SixLabors.ImageSharp.IO.BufferedReadStream stream, int byteCount, int stripHeight, System.Span<byte> buffer, System.Threading.CancellationToken cancellationToken) Line 52	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.Tiff.Compression.TiffBaseDecompressor.Decompress(SixLabors.ImageSharp.IO.BufferedReadStream stream, ulong stripOffset, ulong stripByteCount, int stripHeight, System.Span<byte> buffer, System.Threading.CancellationToken cancellationToken) Line 42	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.Tiff.TiffDecoderCore.DecodeStripsChunky<SixLabors.ImageSharp.PixelFormats.Rgba32>(SixLabors.ImageSharp.ImageFrame<SixLabors.ImageSharp.PixelFormats.Rgba32> frame, int rowsPerStrip, System.Span<ulong> stripOffsets, System.Span<ulong> stripByteCounts, System.Threading.CancellationToken cancellationToken) Line 488	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.Tiff.TiffDecoderCore.DecodeImageWithStrips<SixLabors.ImageSharp.PixelFormats.Rgba32>(SixLabors.ImageSharp.Metadata.Profiles.Exif.ExifProfile tags, SixLabors.ImageSharp.ImageFrame<SixLabors.ImageSharp.PixelFormats.Rgba32> frame, System.Threading.CancellationToken cancellationToken) Line 312	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.Tiff.TiffDecoderCore.DecodeFrame<SixLabors.ImageSharp.PixelFormats.Rgba32>(SixLabors.ImageSharp.Metadata.Profiles.Exif.ExifProfile tags, System.Threading.CancellationToken cancellationToken) Line 256	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.Tiff.TiffDecoderCore.Decode<SixLabors.ImageSharp.PixelFormats.Rgba32>(SixLabors.ImageSharp.IO.BufferedReadStream stream, System.Threading.CancellationToken cancellationToken) Line 174	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.ImageDecoderCore.Decode<SixLabors.ImageSharp.PixelFormats.Rgba32>(SixLabors.ImageSharp.Configuration configuration, System.IO.Stream stream, System.Threading.CancellationToken cancellationToken) Line 82	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.Tiff.TiffDecoder.Decode<SixLabors.ImageSharp.PixelFormats.Rgba32>(SixLabors.ImageSharp.Formats.DecoderOptions options, System.IO.Stream stream, System.Threading.CancellationToken cancellationToken) Line 38	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.Tiff.TiffDecoder.Decode(SixLabors.ImageSharp.Formats.DecoderOptions options, System.IO.Stream stream, System.Threading.CancellationToken cancellationToken) Line 47	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.ImageDecoder.Decode.AnonymousMethod__0(System.IO.Stream s) Line 36	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.ImageDecoder.WithSeekableStream.__PerformActionAndResetPosition|11_0<SixLabors.ImageSharp.Image>(System.IO.Stream s, long position, ref SixLabors.ImageSharp.Formats.ImageDecoder.<>c__DisplayClass11_0<SixLabors.ImageSharp.Image> value) Line 194	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.ImageDecoder.WithSeekableStream<SixLabors.ImageSharp.Image>(SixLabors.ImageSharp.Formats.DecoderOptions options, System.IO.Stream stream, System.Func<System.IO.Stream, SixLabors.ImageSharp.Image> action) Line 209	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Formats.ImageDecoder.Decode(SixLabors.ImageSharp.Formats.DecoderOptions options, System.IO.Stream stream) Line 33	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Image.Decode(SixLabors.ImageSharp.Formats.DecoderOptions options, System.IO.Stream stream) Line 138	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Image.Load.AnonymousMethod__0(System.IO.Stream s) Line 171	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Image.WithSeekableStream<SixLabors.ImageSharp.Image>(SixLabors.ImageSharp.Formats.DecoderOptions options, System.IO.Stream stream, System.Func<System.IO.Stream, SixLabors.ImageSharp.Image> action) Line 301	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Image.Load(SixLabors.ImageSharp.Formats.DecoderOptions options, System.IO.Stream stream) Line 171	C#
 	SixLabors.ImageSharp.dll!SixLabors.ImageSharp.Image.Load(SixLabors.ImageSharp.Formats.DecoderOptions options, string path) Line 182	C#

Images

No response

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