diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBitReader.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBitReader.cs index 0877dbc922..e71d86a1d9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBitReader.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBitReader.cs @@ -22,6 +22,9 @@ internal struct JpegBitReader // 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 JpegBitReader(BufferedReadStream stream) { this.stream = stream; @@ -31,6 +34,7 @@ public JpegBitReader(BufferedReadStream stream) this.MarkerPosition = 0; this.badData = false; this.NoData = false; + this.eofHitCount = 0; } /// @@ -219,11 +223,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 c8d93f6e9e..6a94a98ac6 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -364,4 +364,15 @@ public void Issue2517_DecodeWorks(TestImageProvider provider) image.DebugSave(provider); image.CompareToOriginal(provider); } + + // 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.Instance); + image.DebugSave(provider); + image.CompareToOriginal(provider); + } } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 6be8ff6a68..5da581e52f 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -316,6 +316,7 @@ public static class Issues public const string HangBadScan = "Jpg/issues/Hang_C438A851.jpg"; public const string Issue2517 = "Jpg/issues/issue2517-bad-d7.jpg"; public const string Issue2067_CommentMarker = "Jpg/issues/issue-2067-comment.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