Browse Source

Add tests and fix for handling invalid input.

pull/1059/head
James Jackson-South 6 years ago
parent
commit
8762bdecce
  1. 10
      src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs
  2. 4
      src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs
  3. 20
      src/ImageSharp/Image.Decode.cs
  4. 14
      tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs

10
src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs

@ -22,9 +22,13 @@ namespace SixLabors.ImageSharp.Formats.Bmp
private bool IsSupportedFileFormat(ReadOnlySpan<byte> 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;
}
}
}

4
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;
}
}
}

20
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
/// <returns>The mime type or null if none found.</returns>
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);
}
}

14
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));

Loading…
Cancel
Save