From f78f2344142baf8159f800f5e8b54d6db0007563 Mon Sep 17 00:00:00 2001 From: Brian Berns Date: Tue, 16 Sep 2025 23:48:08 -0400 Subject: [PATCH 1/4] Fixed check for buffer overflow. --- .../Formats/Tiff/Compression/Decompressors/LzwString.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwString.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwString.cs index e6895d67cd..c56b2a6833 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwString.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwString.cs @@ -77,9 +77,9 @@ public class LzwString LzwString e = this; int endIdx = this.Length - 1; - if (endIdx >= buffer.Length) + if (offset + endIdx >= buffer.Length) { - TiffThrowHelper.ThrowImageFormatException("Error reading lzw compressed stream. Either pixel buffer to write to is to small or code length is invalid!"); + TiffThrowHelper.ThrowImageFormatException("Error reading lzw compressed stream. Either pixel buffer to write to is too small or code length is invalid!"); } for (int i = endIdx; i >= 0; i--) From 385a9404c059e98cc0fedb5051245dae3767b20f Mon Sep 17 00:00:00 2001 From: Brian Berns Date: Wed, 17 Sep 2025 00:34:00 -0400 Subject: [PATCH 2/4] If string is too long, skip bytes at the end instead of throwing an exception. --- .../Compression/Decompressors/LzwString.cs | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwString.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwString.cs index c56b2a6833..e8a62e754e 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwString.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwString.cs @@ -69,25 +69,33 @@ public class LzwString return 0; } - if (this.Length == 1) + int available = buffer.Length - offset; + if (available <= 0) { - buffer[offset] = this.value; - return 1; + return 0; + } + + int numToWrite = this.Length; + if (numToWrite > available) + { + numToWrite = available; } LzwString e = this; - int endIdx = this.Length - 1; - if (offset + endIdx >= buffer.Length) + + // if string is too long, skip bytes at the end + int toSkip = this.Length - numToWrite; + for (int i = 0; i < toSkip; i++) { - TiffThrowHelper.ThrowImageFormatException("Error reading lzw compressed stream. Either pixel buffer to write to is too small or code length is invalid!"); + e = e.previous; } - for (int i = endIdx; i >= 0; i--) + for (int i = numToWrite - 1; i >= 0; i--) { buffer[offset + i] = e.value; e = e.previous; } - return this.Length; + return numToWrite; } } From 5eaeafc9547883a9e9948131b26996e3b365380c Mon Sep 17 00:00:00 2001 From: Brian Berns Date: Sun, 28 Sep 2025 13:02:17 -0400 Subject: [PATCH 3/4] Added test case for issue #2983. --- tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs | 5 +++++ tests/ImageSharp.Tests/TestImages.cs | 1 + 2 files changed, 6 insertions(+) diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs index 5dd1f7884f..26dc4f5878 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs @@ -833,4 +833,9 @@ public class TiffDecoderTests : TiffDecoderBaseTester [WithFile(ExtraSamplesUnspecified, PixelTypes.Rgba32)] public void TiffDecoder_CanDecode_ExtraSamplesUnspecified(TestImageProvider provider) where TPixel : unmanaged, IPixel => TestTiffDecoder(provider); + + [Theory] + [WithFile(Issue2983, PixelTypes.Rgba32)] + public void TiffDecoder_CanDecode_Issue2983(TestImageProvider provider) + where TPixel : unmanaged, IPixel => TestTiffDecoder(provider); } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 9a5cfc706e..3e5b3b7120 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -1164,6 +1164,7 @@ public static class TestImages public const string IptcData = "Tiff/iptc.tiff"; public const string Issue2909 = "Tiff/Issues/Issue2909.tiff"; + public const string Issue2983 = "Tiff/Issues/Issue2983.tiff"; public static readonly string[] Multiframes = [MultiframeDeflateWithPreview, MultiframeLzwPredictor /*, MultiFrameDifferentSize, MultiframeDifferentSizeTiled, MultiFrameDifferentVariants,*/ ]; From 336b6a22f6fce033328838f0895848c109b17e3b Mon Sep 17 00:00:00 2001 From: Brian Berns Date: Mon, 29 Sep 2025 01:29:09 -0400 Subject: [PATCH 4/4] Added TIFF image for unit test. --- tests/Images/Input/Tiff/Issues/Issue2983.tiff | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/Images/Input/Tiff/Issues/Issue2983.tiff diff --git a/tests/Images/Input/Tiff/Issues/Issue2983.tiff b/tests/Images/Input/Tiff/Issues/Issue2983.tiff new file mode 100644 index 0000000000..7332ca42a9 --- /dev/null +++ b/tests/Images/Input/Tiff/Issues/Issue2983.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7bfe1d8660d11111cdf2674aedc43c1362dc8c2ecfab9b74b43a06c7c195863e +size 13311100