From 55e49262df9a057dff9b7807ed1b7bdb49187c3f Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 30 Jul 2025 11:31:33 +1000 Subject: [PATCH 1/4] Fix #2953 --- .gitattributes | 1 - src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 5 +++ .../Formats/Gif/GifDecoderTests.cs | 33 +++++++++++++------ tests/ImageSharp.Tests/TestImages.cs | 1 + tests/Images/Input/Gif/issues/issue_2953.gif | 3 ++ 5 files changed, 32 insertions(+), 11 deletions(-) create mode 100644 tests/Images/Input/Gif/issues/issue_2953.gif diff --git a/.gitattributes b/.gitattributes index f97695f901..355b64dce1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -115,7 +115,6 @@ *.jpg filter=lfs diff=lfs merge=lfs -text *.jpeg filter=lfs diff=lfs merge=lfs -text *.bmp filter=lfs diff=lfs merge=lfs -text -*.BMP filter=lfs diff=lfs merge=lfs -text *.gif filter=lfs diff=lfs merge=lfs -text *.png filter=lfs diff=lfs merge=lfs -text *.tif filter=lfs diff=lfs merge=lfs -text diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index 8fdaef9e0f..886f667e4c 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -402,6 +402,11 @@ private void ReadComments(BufferedReadStream stream) GifThrowHelper.ThrowInvalidImageContentException($"Gif comment length '{length}' exceeds max '{GifConstants.MaxCommentSubBlockLength}' of a comment data block"); } + if (length == -1) + { + GifThrowHelper.ThrowInvalidImageContentException("Unexpected end of stream while reading gif comment"); + } + if (this.skipMetadata) { stream.Seek(length, SeekOrigin.Current); diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs index 4e42722d2c..124a2688a3 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs @@ -183,16 +183,16 @@ public void Issue1530_BadDescriptorDimensions(TestImageProvider image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact); } - // https://github.com/SixLabors/ImageSharp/issues/2758 - [Theory] - [WithFile(TestImages.Gif.Issues.Issue2758, PixelTypes.Rgba32)] - public void Issue2758_BadDescriptorDimensions(TestImageProvider provider) - where TPixel : unmanaged, IPixel - { - using Image image = provider.GetImage(); - image.DebugSaveMultiFrame(provider); - image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact); - } + // https://github.com/SixLabors/ImageSharp/issues/2758 + [Theory] + [WithFile(TestImages.Gif.Issues.Issue2758, PixelTypes.Rgba32)] + public void Issue2758_BadDescriptorDimensions(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using Image image = provider.GetImage(); + image.DebugSaveMultiFrame(provider); + image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact); + } // https://github.com/SixLabors/ImageSharp/issues/405 [Theory] @@ -329,5 +329,18 @@ public void Issue2859_LZWPixelStackOverflow(TestImageProvider pr image.DebugSaveMultiFrame(provider); image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact); } + + // https://github.com/SixLabors/ImageSharp/issues/2953 + [Theory] + [WithFile(TestImages.Gif.Issues.Issue2953, PixelTypes.Rgba32)] + public void Issue2953(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + // We should throw a InvalidImageContentException when trying to identify or load an invalid GIF file. + var testFile = TestFile.Create(provider.SourceFileOrDescription); + + Assert.Throws(() => Image.Identify(testFile.FullPath)); + Assert.Throws(() => Image.Load(testFile.FullPath)); + } } } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 9ee63e5636..9210be394e 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -468,6 +468,7 @@ public static class Issues public const string Issue2758 = "Gif/issues/issue_2758.gif"; public const string Issue2859_A = "Gif/issues/issue_2859_A.gif"; public const string Issue2859_B = "Gif/issues/issue_2859_B.gif"; + public const string Issue2953 = "Gif/issues/issue_2953.gif"; } public static readonly string[] All = { Rings, Giphy, Cheers, Trans, Kumin, Leo, Ratio4x1, Ratio1x4 }; diff --git a/tests/Images/Input/Gif/issues/issue_2953.gif b/tests/Images/Input/Gif/issues/issue_2953.gif new file mode 100644 index 0000000000..98c06e5c58 --- /dev/null +++ b/tests/Images/Input/Gif/issues/issue_2953.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4fa4a002b264a41677cc10f115f3572111852993a53ee8cea5f4ec0bf8dec195 +size 40 From a96a9be1f3642b880134d29b039c7f9a9a0f6f4f Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 30 Jul 2025 12:27:44 +1000 Subject: [PATCH 2/4] Override restore sources --- Directory.Build.props | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Directory.Build.props b/Directory.Build.props index b46c0f19f2..524cf27890 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -33,4 +33,13 @@ true + + + + + https://api.nuget.org/v3/index.json; + https://f.feedz.io/sixlabors/sixlabors/nuget/index.json; + https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json; + + From d284a44b41d3f4589f5b4f4142d340c8b8134975 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 30 Jul 2025 12:49:10 +1000 Subject: [PATCH 3/4] Skip fragile BMP test on Linux --- tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index acc4c201b7..e26ff5d768 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -611,6 +611,13 @@ public void BmpDecoder_CanDecode_Os2v2Header(TestImageProvider p public void BmpDecoder_CanDecode_Os2BitmapArray(TestImageProvider provider) where TPixel : unmanaged, IPixel { + if (TestEnvironment.IsLinux && TestEnvironment.RunsOnCI) + { + // Build runs are failing on CI only. + // System.NotSupportedException : ImageSharp does not support this BMP file. File header bitmap type marker '25974'. + return; + } + using (Image image = provider.GetImage(BmpDecoder)) { image.DebugSave(provider); From 075f3c8d734cc9e4ecbf42f9eff771e61ff3a533 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 30 Jul 2025 12:53:56 +1000 Subject: [PATCH 4/4] Restore gitattributes --- .gitattributes | 1 + tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs | 7 ------- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.gitattributes b/.gitattributes index 355b64dce1..f97695f901 100644 --- a/.gitattributes +++ b/.gitattributes @@ -115,6 +115,7 @@ *.jpg filter=lfs diff=lfs merge=lfs -text *.jpeg filter=lfs diff=lfs merge=lfs -text *.bmp filter=lfs diff=lfs merge=lfs -text +*.BMP filter=lfs diff=lfs merge=lfs -text *.gif filter=lfs diff=lfs merge=lfs -text *.png filter=lfs diff=lfs merge=lfs -text *.tif filter=lfs diff=lfs merge=lfs -text diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index e26ff5d768..acc4c201b7 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -611,13 +611,6 @@ public void BmpDecoder_CanDecode_Os2v2Header(TestImageProvider p public void BmpDecoder_CanDecode_Os2BitmapArray(TestImageProvider provider) where TPixel : unmanaged, IPixel { - if (TestEnvironment.IsLinux && TestEnvironment.RunsOnCI) - { - // Build runs are failing on CI only. - // System.NotSupportedException : ImageSharp does not support this BMP file. File header bitmap type marker '25974'. - return; - } - using (Image image = provider.GetImage(BmpDecoder)) { image.DebugSave(provider);