From 7781fbd879e29b2c7a79438eb4937ac646ea91b7 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sat, 5 Sep 2026 01:04:43 +1000 Subject: [PATCH] Validate decoded image dimensions --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 5 +++++ src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 9 ++++----- src/ImageSharp/Formats/Tga/TgaDecoderCore.cs | 4 ++-- .../Formats/InvalidImageDimensionsTests.cs | 18 ++++++++++++++++++ 4 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 tests/ImageSharp.Tests/Formats/InvalidImageDimensionsTests.cs diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index aba1243d77..db7719019b 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -1560,6 +1560,11 @@ internal sealed class BmpDecoderCore : ImageDecoderCore this.infoHeader.Height = -this.infoHeader.Height; } + if (this.infoHeader.Width <= 0 || this.infoHeader.Height <= 0) + { + BmpThrowHelper.ThrowInvalidImageContentException("Width and height must be greater than 0."); + } + int bytesPerColorMapEntry = 4; int colorMapSizeBytes = -1; if (this.infoHeader.ClrUsed == 0) diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index e4ffd42823..0a06f4915b 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -261,11 +261,6 @@ internal sealed class GifDecoderCore : ImageDecoderCore this.currentLocalColorTable?.Dispose(); } - if (this.logicalScreenDescriptor.Width == 0 && this.logicalScreenDescriptor.Height == 0) - { - GifThrowHelper.ThrowNoHeader(); - } - // Ignoring a malformed ancillary extension must not let identify succeed for a file // that never contained any readable image frame data. if (previousFrame is null) @@ -328,6 +323,10 @@ internal sealed class GifDecoderCore : ImageDecoderCore } this.logicalScreenDescriptor = GifLogicalScreenDescriptor.Parse(this.buffer); + if (this.logicalScreenDescriptor.Width == 0 || this.logicalScreenDescriptor.Height == 0) + { + GifThrowHelper.ThrowInvalidImageContentException("Width and height must be greater than 0."); + } } /// diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs index ead157986a..86f80530fb 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs @@ -72,9 +72,9 @@ internal sealed class TgaDecoderCore : ImageDecoderCore TgaThrowHelper.ThrowNotSupportedException($"Unknown tga colormap type {this.fileHeader.ColorMapType} found"); } - if (this.fileHeader.Width == 0 || this.fileHeader.Height == 0) + if (this.fileHeader.Width <= 0 || this.fileHeader.Height <= 0) { - throw new UnknownImageFormatException("Width or height cannot be 0"); + TgaThrowHelper.ThrowInvalidImageContentException("Width and height must be greater than 0."); } Image image = new(this.configuration, this.fileHeader.Width, this.fileHeader.Height, this.metadata); diff --git a/tests/ImageSharp.Tests/Formats/InvalidImageDimensionsTests.cs b/tests/ImageSharp.Tests/Formats/InvalidImageDimensionsTests.cs new file mode 100644 index 0000000000..bcf7df5984 --- /dev/null +++ b/tests/ImageSharp.Tests/Formats/InvalidImageDimensionsTests.cs @@ -0,0 +1,18 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Tests.Formats; + +public class InvalidImageDimensionsTests +{ + [Theory] + [InlineData("Qk1GAAAAAAAAADYAAAAoAAAAAgACAAAAAAABABgAAAAAABAAAAATCwAAEwsAAAAAAAAAAAAAAAD/AP8AAAAAAP8A/wAAAA==")] + [InlineData("R0lGODdhAgIAAIEAAAD/AP8AAAAA/wAAACwAAAQAAgACAAAIBwADABAQICAAOw==")] + [InlineData("AAACAAAAAAAAAAAAAgDCsRgAAgAAAP8A/wD/AAAA//8=")] + public void Load_WithNonPositiveDimensions_ThrowsInvalidImageContentException(string encodedData) + { + byte[] data = Convert.FromBase64String(encodedData); + + Assert.Throws(() => Image.Load(data)); + } +}