From bb82f79db0197166271d4355b5fb5ceda370a906 Mon Sep 17 00:00:00 2001 From: antonfirsov Date: Mon, 24 Feb 2025 18:18:54 +0100 Subject: [PATCH] #2701 to 2.1.x [copy] --- .../Components/Decoder/HuffmanScanBuffer.cs | 17 +++++++++++++---- .../Formats/Jpg/JpegDecoderTests.cs | 13 +++++++++++++ tests/ImageSharp.Tests/TestImages.cs | 3 ++- tests/Images/Input/Jpg/issues/Issue2638.jpg | 3 +++ 4 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 tests/Images/Input/Jpg/issues/Issue2638.jpg diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs index 39e606fd39..c6fe34e22e 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs @@ -22,6 +22,9 @@ internal struct HuffmanScanBuffer // Whether there is no more good data to pull from the stream for the current mcu. private bool badData; + // How many times have we hit the eof. + private int eofHitCount; + public HuffmanScanBuffer(BufferedReadStream stream) { this.stream = stream; @@ -31,6 +34,7 @@ public HuffmanScanBuffer(BufferedReadStream stream) this.MarkerPosition = 0; this.badData = false; this.NoData = false; + this.eofHitCount = 0; } /// @@ -218,11 +222,16 @@ private int ReadStream() // we know we have hit the EOI and completed decoding the scan buffer. if (value == -1 || (this.badData && this.data == 0 && this.stream.Position >= this.stream.Length)) { - // We've encountered the end of the file stream which means there's no EOI marker + // We've hit the end of the file stream more times than allowed which means there's no EOI marker // in the image or the SOS marker has the wrong dimensions set. - this.badData = true; - this.NoData = true; - value = 0; + if (this.eofHitCount > JpegConstants.Huffman.FetchLoop) + { + this.badData = true; + this.NoData = true; + value = 0; + } + + this.eofHitCount++; } return value; diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs index 708e859eed..284e4fa254 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -229,6 +229,19 @@ public void Issue2133_DeduceColorSpace(TestImageProvider provide } } + // https://github.com/SixLabors/ImageSharp/issues/2638 + [Theory] + [WithFile(TestImages.Jpeg.Issues.Issue2638, PixelTypes.Rgba32)] + public void Issue2638_DecodeWorks(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using (Image image = provider.GetImage(JpegDecoder)) + { + image.DebugSave(provider); + image.CompareToOriginal(provider); + } + } + // DEBUG ONLY! // The PDF.js output should be saved by "tests\ImageSharp.Tests\Formats\Jpg\pdfjs\jpeg-converter.htm" // into "\tests\Images\ActualOutput\JpegDecoderTests\" diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index bb646800d0..9ee63e5636 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -269,7 +269,8 @@ public static class Issues public const string ValidExifArgumentNullExceptionOnEncode = "Jpg/issues/Issue2087-exif-null-reference-on-encode.jpg"; public const string Issue2133DeduceColorSpace = "Jpg/issues/Issue2133.jpg"; public const string HangBadScan = "Jpg/issues/Hang_C438A851.jpg"; - public const string Issue2758 = "Jpg/issues/issue-2758.jpg"; + public const string Issue2758 = "Jpg/issues/issue-2758.jpg"; + public const string Issue2638 = "Jpg/issues/Issue2638.jpg"; public static class Fuzz { diff --git a/tests/Images/Input/Jpg/issues/Issue2638.jpg b/tests/Images/Input/Jpg/issues/Issue2638.jpg new file mode 100644 index 0000000000..f42d67b0e8 --- /dev/null +++ b/tests/Images/Input/Jpg/issues/Issue2638.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:208d5b0b727bbef120a7e090e020a48f99c9e264c2d3939ba749f8620853c1fe +size 70876