From 20260cd533141d34392aa5a176deb13f94b76717 Mon Sep 17 00:00:00 2001 From: Visual-Vincent Date: Fri, 24 Jan 2025 15:12:17 +0100 Subject: [PATCH 1/3] Backported #2701 (fixes #2638) to release 2.1.x --- .../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 1ba9ef2ef3..49be44fe72 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 From 9e970fc89a5830caac4a8d088410f584b500f4d9 Mon Sep 17 00:00:00 2001 From: Visual-Vincent Date: Fri, 31 Jan 2025 20:41:01 +0100 Subject: [PATCH 2/3] Updated versions of GitHub Actions --- .github/workflows/build-and-test.yml | 18 +++++++++--------- .github/workflows/code-coverage.yml | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 5b3d294bc5..9c0d874a53 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -81,7 +81,7 @@ jobs: git config --global core.longpaths true - name: Git Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 submodules: recursive @@ -91,7 +91,7 @@ jobs: run: git lfs ls-files -l | cut -d' ' -f1 | sort > .lfs-assets-id - name: Git Setup LFS Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: lfs-cache with: path: .git/lfs @@ -101,10 +101,10 @@ jobs: run: git lfs pull - name: NuGet Install - uses: NuGet/setup-nuget@v1 + uses: NuGet/setup-nuget@v2 - name: NuGet Setup Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: nuget-cache with: path: ~/.nuget @@ -112,7 +112,7 @@ jobs: restore-keys: ${{ runner.os }}-nuget- - name: DotNet Setup - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v4 with: dotnet-version: | 6.0.x @@ -151,7 +151,7 @@ jobs: XUNIT_PATH: .\tests\ImageSharp.Tests # Required for xunit - name: Export Failed Output - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: failure() with: name: actual_output_${{ runner.os }}_${{ matrix.options.framework }}${{ matrix.options.runtime }}.zip @@ -172,16 +172,16 @@ jobs: git config --global core.longpaths true - name: Git Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 submodules: recursive - name: NuGet Install - uses: NuGet/setup-nuget@v1 + uses: NuGet/setup-nuget@v2 - name: NuGet Setup Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: nuget-cache with: path: ~/.nuget diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml index 2b14f2a4b7..3da95ea529 100644 --- a/.github/workflows/code-coverage.yml +++ b/.github/workflows/code-coverage.yml @@ -24,7 +24,7 @@ jobs: git config --global core.longpaths true - name: Git Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: fetch-depth: 0 submodules: recursive @@ -34,7 +34,7 @@ jobs: run: git lfs ls-files -l | cut -d' ' -f1 | sort > .lfs-assets-id - name: Git Setup LFS Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: lfs-cache with: path: .git/lfs @@ -44,10 +44,10 @@ jobs: run: git lfs pull - name: NuGet Install - uses: NuGet/setup-nuget@v1 + uses: NuGet/setup-nuget@v2 - name: NuGet Setup Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: nuget-cache with: path: ~/.nuget @@ -68,14 +68,14 @@ jobs: XUNIT_PATH: .\tests\ImageSharp.Tests # Required for xunit - name: Export Failed Output - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: failure() with: name: actual_output_${{ runner.os }}_${{ matrix.options.framework }}${{ matrix.options.runtime }}.zip path: tests/Images/ActualOutput/ - name: Codecov Update - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v4 if: matrix.options.codecov == true && startsWith(github.repository, 'SixLabors') with: flags: unittests From 6d54c3b0d1a1022d237a3f4559fd2875fcb9635a Mon Sep 17 00:00:00 2001 From: antonfirsov Date: Mon, 24 Feb 2025 18:12:29 +0100 Subject: [PATCH 3/3] undo yaml changes --- .github/workflows/build-and-test.yml | 16 ++++++++-------- .github/workflows/code-coverage.yml | 12 ++++++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index d809c745eb..7ccf2fc8ec 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -91,7 +91,7 @@ jobs: git config --global core.longpaths true - name: Git Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v2 with: fetch-depth: 0 submodules: recursive @@ -101,7 +101,7 @@ jobs: run: git lfs ls-files -l | cut -d' ' -f1 | sort > .lfs-assets-id - name: Git Setup LFS Cache - uses: actions/cache@v4 + uses: actions/cache@v2 id: lfs-cache with: path: .git/lfs @@ -111,10 +111,10 @@ jobs: run: git lfs pull - name: NuGet Install - uses: NuGet/setup-nuget@v2 + uses: NuGet/setup-nuget@v1 - name: NuGet Setup Cache - uses: actions/cache@v4 + uses: actions/cache@v2 id: nuget-cache with: path: ~/.nuget @@ -122,7 +122,7 @@ jobs: restore-keys: ${{ runner.os }}-nuget- - name: DotNet Setup - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@v1 with: dotnet-version: | 6.0.x @@ -182,16 +182,16 @@ jobs: git config --global core.longpaths true - name: Git Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v2 with: fetch-depth: 0 submodules: recursive - name: NuGet Install - uses: NuGet/setup-nuget@v2 + uses: NuGet/setup-nuget@v1 - name: NuGet Setup Cache - uses: actions/cache@v4 + uses: actions/cache@v2 id: nuget-cache with: path: ~/.nuget diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml index 3da95ea529..2b14f2a4b7 100644 --- a/.github/workflows/code-coverage.yml +++ b/.github/workflows/code-coverage.yml @@ -24,7 +24,7 @@ jobs: git config --global core.longpaths true - name: Git Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v2 with: fetch-depth: 0 submodules: recursive @@ -34,7 +34,7 @@ jobs: run: git lfs ls-files -l | cut -d' ' -f1 | sort > .lfs-assets-id - name: Git Setup LFS Cache - uses: actions/cache@v4 + uses: actions/cache@v2 id: lfs-cache with: path: .git/lfs @@ -44,10 +44,10 @@ jobs: run: git lfs pull - name: NuGet Install - uses: NuGet/setup-nuget@v2 + uses: NuGet/setup-nuget@v1 - name: NuGet Setup Cache - uses: actions/cache@v4 + uses: actions/cache@v2 id: nuget-cache with: path: ~/.nuget @@ -68,14 +68,14 @@ jobs: XUNIT_PATH: .\tests\ImageSharp.Tests # Required for xunit - name: Export Failed Output - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v2 if: failure() with: name: actual_output_${{ runner.os }}_${{ matrix.options.framework }}${{ matrix.options.runtime }}.zip path: tests/Images/ActualOutput/ - name: Codecov Update - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v1 if: matrix.options.codecov == true && startsWith(github.repository, 'SixLabors') with: flags: unittests