From 43f952cf00e0ff8759f967ff95beafa92ab1b526 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Mon, 23 Mar 2026 09:37:53 +0100 Subject: [PATCH 1/2] Throw InvalidImageContentException when frame control chunk does not have enough data --- src/ImageSharp/Formats/Png/Chunks/FrameControl.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Png/Chunks/FrameControl.cs b/src/ImageSharp/Formats/Png/Chunks/FrameControl.cs index 91f79c8154..7288df8a0e 100644 --- a/src/ImageSharp/Formats/Png/Chunks/FrameControl.cs +++ b/src/ImageSharp/Formats/Png/Chunks/FrameControl.cs @@ -147,7 +147,13 @@ internal readonly struct FrameControl /// The data to parse. /// The parsed fcTL. public static FrameControl Parse(ReadOnlySpan data) - => new( + { + if (data.Length < Size) + { + PngThrowHelper.ThrowInvalidImageContentException("The Frame Control Chunk does not contain enough data!"); + } + + return new( sequenceNumber: BinaryPrimitives.ReadUInt32BigEndian(data[..4]), width: BinaryPrimitives.ReadUInt32BigEndian(data[4..8]), height: BinaryPrimitives.ReadUInt32BigEndian(data[8..12]), @@ -157,4 +163,5 @@ internal readonly struct FrameControl delayDenominator: BinaryPrimitives.ReadUInt16BigEndian(data[22..24]), disposalMode: (FrameDisposalMode)(data[24] + 1), blendMode: (FrameBlendMode)data[25]); + } } From 4e81c02b5dcda32dddbc62dc7e1679c6b31f41c5 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Mon, 23 Mar 2026 09:44:15 +0100 Subject: [PATCH 2/2] Add test case for Issue #3093 --- .../Formats/Png/Chunks/FrameControl.cs | 2 +- .../Formats/Png/PngDecoderTests.Chunks.cs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Png/Chunks/FrameControl.cs b/src/ImageSharp/Formats/Png/Chunks/FrameControl.cs index 7288df8a0e..0038b41344 100644 --- a/src/ImageSharp/Formats/Png/Chunks/FrameControl.cs +++ b/src/ImageSharp/Formats/Png/Chunks/FrameControl.cs @@ -150,7 +150,7 @@ internal readonly struct FrameControl { if (data.Length < Size) { - PngThrowHelper.ThrowInvalidImageContentException("The Frame Control Chunk does not contain enough data!"); + PngThrowHelper.ThrowInvalidImageContentException("The frame control chunk does not contain enough data!"); } return new( diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs index 03dc040186..ed33f71636 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs @@ -92,6 +92,22 @@ public partial class PngDecoderTests Assert.Equal("pHYs chunk is too short", exception.Message); } + // https://github.com/SixLabors/ImageSharp/issues/3093 + [Fact] + public void Decode_TruncatedFrameControlChunk_ExceptionIsThrown() + { + // PNG signature + truncated frame control chunk + byte[] payload = Convert.FromHexString( + "89504e470d0a1a0a424d3a00000000007f000000000028030405060000000100" + + "000101002000000000000000000000000000ff00006663544cff190000000000" + + "010000424d000100000101002000000000"); + + using MemoryStream stream = new(payload); + InvalidImageContentException exception = Assert.Throws(() => Image.Load(stream)); + + Assert.Equal("The frame control chunk does not contain enough data!", exception.Message); + } + // https://github.com/SixLabors/ImageSharp/issues/3079 [Fact] public void Decode_CompressedTxtChunk_WithTruncatedData_DoesNotThrow()