From d7f7d5ae139b74c2eec0b3959048ad6e4c584b4a Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 10 Jul 2024 21:20:44 +1000 Subject: [PATCH 1/2] Correctly break during decoding --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 12 ++++++------ .../ImageSharp.Tests/Formats/Png/PngDecoderTests.cs | 10 ++++++++++ tests/ImageSharp.Tests/TestImages.cs | 3 +++ tests/Images/Input/Png/issues/Issue_2752.png | 3 +++ 4 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 tests/Images/Input/Png/issues/Issue_2752.png diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index dd5e16d7be..89e5fb8d99 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -204,18 +204,13 @@ public Image Decode(BufferedReadStream stream, CancellationToken break; case PngChunkType.FrameControl: frameCount++; - if (frameCount == this.maxFrames) - { - break; - } - currentFrame = null; currentFrameControl = this.ReadFrameControlChunk(chunk.Data.GetSpan()); break; case PngChunkType.FrameData: if (frameCount == this.maxFrames) { - break; + goto EOF; } if (image is null) @@ -271,6 +266,11 @@ public Image Decode(BufferedReadStream stream, CancellationToken previousFrameControl = currentFrameControl; } + if (frameCount == this.maxFrames) + { + goto EOF; + } + break; case PngChunkType.Palette: this.palette = chunk.Data.GetSpan().ToArray(); diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index 8d4bc3f461..11af57e39f 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -701,4 +701,14 @@ public void Decode_BadPalette(string file) string path = Path.GetFullPath(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, file)); using Image image = Image.Load(path); } + + [Theory] + [WithFile(TestImages.Png.Issue2752, PixelTypes.Rgba32)] + public void CanDecodeJustOneFrame(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + DecoderOptions options = new() { MaxFrames = 1 }; + using Image image = provider.GetImage(PngDecoder.Instance, options); + Assert.Equal(1, image.Frames.Count); + } } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index c571619d64..79f22ffbe5 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -156,6 +156,9 @@ public static class Png // Issue 2668: https://github.com/SixLabors/ImageSharp/issues/2668 public const string Issue2668 = "Png/issues/Issue_2668.png"; + // Issue 2752: https://github.com/SixLabors/ImageSharp/issues/2752 + public const string Issue2752 = "Png/issues/Issue_2752.png"; + public static class Bad { public const string MissingDataChunk = "Png/xdtn0g01.png"; diff --git a/tests/Images/Input/Png/issues/Issue_2752.png b/tests/Images/Input/Png/issues/Issue_2752.png new file mode 100644 index 0000000000..05863fbf2a --- /dev/null +++ b/tests/Images/Input/Png/issues/Issue_2752.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2d4cb44eea721009c616de30a1f18c1de59635de4b313b13d685456a529ced97 +size 5590983 From 8adcabec6ebe0a158daa2da0a5e7cb211d834720 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 15 Jul 2024 20:11:52 +1000 Subject: [PATCH 2/2] Use >= to compare. --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 89e5fb8d99..f2f06a2c73 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -208,7 +208,7 @@ public Image Decode(BufferedReadStream stream, CancellationToken currentFrameControl = this.ReadFrameControlChunk(chunk.Data.GetSpan()); break; case PngChunkType.FrameData: - if (frameCount == this.maxFrames) + if (frameCount >= this.maxFrames) { goto EOF; } @@ -266,7 +266,7 @@ public Image Decode(BufferedReadStream stream, CancellationToken previousFrameControl = currentFrameControl; } - if (frameCount == this.maxFrames) + if (frameCount >= this.maxFrames) { goto EOF; } @@ -389,7 +389,7 @@ public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellat break; case PngChunkType.FrameControl: ++frameCount; - if (frameCount == this.maxFrames) + if (frameCount >= this.maxFrames) { break; } @@ -397,7 +397,7 @@ public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellat lastFrameControl = this.ReadFrameControlChunk(chunk.Data.GetSpan()); break; case PngChunkType.FrameData: - if (frameCount == this.maxFrames) + if (frameCount >= this.maxFrames) { break; }