diff --git a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs index 3d7510bc2..e1fc9ef1f 100644 --- a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs @@ -22,9 +22,13 @@ namespace SixLabors.ImageSharp.Formats.Bmp private bool IsSupportedFileFormat(ReadOnlySpan header) { - short fileTypeMarker = BinaryPrimitives.ReadInt16LittleEndian(header); - return header.Length >= this.HeaderSize && - (fileTypeMarker == BmpConstants.TypeMarkers.Bitmap || fileTypeMarker == BmpConstants.TypeMarkers.BitmapArray); + if (header.Length >= this.HeaderSize) + { + short fileTypeMarker = BinaryPrimitives.ReadInt16LittleEndian(header); + return fileTypeMarker == BmpConstants.TypeMarkers.Bitmap || fileTypeMarker == BmpConstants.TypeMarkers.BitmapArray; + } + + return false; } } } diff --git a/src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs b/src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs index bd9cfa900..af40c333b 100644 --- a/src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs @@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Formats.Tga { if (header.Length >= this.HeaderSize) { - // There is no magick bytes in a tga file, so at least the image type + // There are no magic bytes in a tga file, so at least the image type // and the colormap type in the header will be checked for a valid value. if (header[1] != 0 && header[1] != 1) { @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Formats.Tga return imageType.IsValid(); } - return true; + return false; } } } diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs index 4521864c3..db6a5e165 100644 --- a/src/ImageSharp/Image.Decode.cs +++ b/src/ImageSharp/Image.Decode.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.IO; using System.Linq; using SixLabors.ImageSharp.Formats; @@ -47,19 +48,26 @@ namespace SixLabors.ImageSharp /// The mime type or null if none found. private static IImageFormat InternalDetectFormat(Stream stream, Configuration config) { - // This is probably a candidate for making into a public API in the future! - int maxHeaderSize = config.MaxHeaderSize; - if (maxHeaderSize <= 0) + // We take a minimum of the stream length vs the max header size and always check below + // to ensure that only formats that headers fit within the given buffer length are tested. + int headerSize = (int)Math.Min(config.MaxHeaderSize, stream.Length); + if (headerSize <= 0) { return null; } - using (IManagedByteBuffer buffer = config.MemoryAllocator.AllocateManagedByteBuffer(maxHeaderSize, AllocationOptions.Clean)) + using (IManagedByteBuffer buffer = config.MemoryAllocator.AllocateManagedByteBuffer(headerSize, AllocationOptions.Clean)) { long startPosition = stream.Position; - stream.Read(buffer.Array, 0, maxHeaderSize); + stream.Read(buffer.Array, 0, headerSize); stream.Position = startPosition; - return config.ImageFormatsManager.FormatDetectors.Select(x => x.DetectFormat(buffer.GetSpan())).LastOrDefault(x => x != null); + + // Does the given stream contain enough data to fit in the header for the format + // and does that data match the format specification? + // Individual formats should still check since they are public. + return config.ImageFormatsManager.FormatDetectors + .Where(x => x.HeaderSize <= headerSize) + .Select(x => x.DetectFormat(buffer.GetSpan())).LastOrDefault(x => x != null); } } diff --git a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs index 835dcb320..1e2846910 100644 --- a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs +++ b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs @@ -191,6 +191,20 @@ namespace SixLabors.ImageSharp.Tests } } + [Fact] + public void IdentifyReturnsNullWithInvalidStream() + { + byte[] invalid = new byte[10]; + + using (var memoryStream = new MemoryStream(invalid)) + { + IImageInfo imageInfo = Image.Identify(memoryStream, out IImageFormat format); + + Assert.Null(imageInfo); + Assert.Null(format); + } + } + private static IImageFormat GetFormat(string format) { return Configuration.Default.ImageFormats.FirstOrDefault(x => x.FileExtensions.Contains(format));