Browse Source

check disposed buffers for decoders

pull/2082/head
Scott Williams 4 years ago
parent
commit
af7d84a376
  1. 9
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  2. 5
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  3. 6
      src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs
  4. 6
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
  5. 62
      src/ImageSharp/Formats/Webp/WebpDecoderCore.cs
  6. 1
      tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
  7. 1
      tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
  8. 15
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs
  9. 1
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  10. 1
      tests/ImageSharp.Tests/Formats/Pbm/PbmDecoderTests.cs
  11. 2
      tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
  12. 1
      tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs
  13. 1
      tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
  14. 1
      tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs
  15. 2
      tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparingUtils.cs

9
src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

@ -122,11 +122,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp
public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
Image<TPixel> image = null;
try
{
int bytesPerColorMapEntry = this.ReadImageHeaders(stream, out bool inverted, out byte[] palette);
var image = new Image<TPixel>(this.Configuration, this.infoHeader.Width, this.infoHeader.Height, this.metadata);
image = new Image<TPixel>(this.Configuration, this.infoHeader.Width, this.infoHeader.Height, this.metadata);
Buffer2D<TPixel> pixels = image.GetRootFramePixelBuffer();
@ -193,8 +194,14 @@ namespace SixLabors.ImageSharp.Formats.Bmp
}
catch (IndexOutOfRangeException e)
{
image?.Dispose();
throw new ImageFormatException("Bitmap does not have a valid format.", e);
}
catch
{
image?.Dispose();
throw;
}
}
/// <inheritdoc />

5
src/ImageSharp/Formats/Gif/GifDecoderCore.cs

@ -151,6 +151,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
}
}
//catch
//{
// image?.Dispose();
// throw;
//}
finally
{
this.globalColorTable?.Dispose();

6
src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs

@ -65,7 +65,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors
jpegDecoder.ParseStream(stream, scanDecoderGray, CancellationToken.None);
// TODO: Should we pass through the CancellationToken from the tiff decoder?
CopyImageBytesToBuffer(buffer, spectralConverterGray.GetPixelBuffer(CancellationToken.None));
using var decompressedBuffer = spectralConverterGray.GetPixelBuffer(CancellationToken.None);
CopyImageBytesToBuffer(buffer, decompressedBuffer);
break;
}
@ -81,7 +82,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors
jpegDecoder.ParseStream(stream, scanDecoder, CancellationToken.None);
// TODO: Should we pass through the CancellationToken from the tiff decoder?
CopyImageBytesToBuffer(buffer, spectralConverter.GetPixelBuffer(CancellationToken.None));
using var decompressedBuffer = spectralConverter.GetPixelBuffer(CancellationToken.None);
CopyImageBytesToBuffer(buffer, decompressedBuffer);
break;
}

6
src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

@ -240,8 +240,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff
var stripOffsetsArray = (Array)tags.GetValueInternal(ExifTag.StripOffsets).GetValue();
var stripByteCountsArray = (Array)tags.GetValueInternal(ExifTag.StripByteCounts).GetValue();
IMemoryOwner<ulong> stripOffsetsMemory = this.ConvertNumbers(stripOffsetsArray, out Span<ulong> stripOffsets);
IMemoryOwner<ulong> stripByteCountsMemory = this.ConvertNumbers(stripByteCountsArray, out Span<ulong> stripByteCounts);
using IMemoryOwner<ulong> stripOffsetsMemory = this.ConvertNumbers(stripOffsetsArray, out Span<ulong> stripOffsets);
using IMemoryOwner<ulong> stripByteCountsMemory = this.ConvertNumbers(stripByteCountsArray, out Span<ulong> stripByteCounts);
if (this.PlanarConfiguration == TiffPlanarConfiguration.Planar)
{
@ -262,8 +262,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
cancellationToken);
}
stripOffsetsMemory?.Dispose();
stripByteCountsMemory?.Dispose();
return frame;
}

62
src/ImageSharp/Formats/Webp/WebpDecoderCore.cs

@ -82,38 +82,48 @@ namespace SixLabors.ImageSharp.Formats.Webp
public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
this.Metadata = new ImageMetadata();
this.currentStream = stream;
Image<TPixel> image = null;
try
{
uint fileSize = this.ReadImageHeader();
this.Metadata = new ImageMetadata();
this.currentStream = stream;
using (this.webImageInfo = this.ReadVp8Info())
{
if (this.webImageInfo.Features is { Animation: true })
{
WebpThrowHelper.ThrowNotSupportedException("Animations are not supported");
}
uint fileSize = this.ReadImageHeader();
var image = new Image<TPixel>(this.Configuration, (int)this.webImageInfo.Width, (int)this.webImageInfo.Height, this.Metadata);
Buffer2D<TPixel> pixels = image.GetRootFramePixelBuffer();
if (this.webImageInfo.IsLossless)
using (this.webImageInfo = this.ReadVp8Info())
{
var losslessDecoder = new WebpLosslessDecoder(this.webImageInfo.Vp8LBitReader, this.memoryAllocator, this.Configuration);
losslessDecoder.Decode(pixels, image.Width, image.Height);
}
else
{
var lossyDecoder = new WebpLossyDecoder(this.webImageInfo.Vp8BitReader, this.memoryAllocator, this.Configuration);
lossyDecoder.Decode(pixels, image.Width, image.Height, this.webImageInfo);
}
if (this.webImageInfo.Features is { Animation: true })
{
WebpThrowHelper.ThrowNotSupportedException("Animations are not supported");
}
// There can be optional chunks after the image data, like EXIF and XMP.
if (this.webImageInfo.Features != null)
{
this.ParseOptionalChunks(this.webImageInfo.Features);
}
image = new Image<TPixel>(this.Configuration, (int)this.webImageInfo.Width, (int)this.webImageInfo.Height, this.Metadata);
Buffer2D<TPixel> pixels = image.GetRootFramePixelBuffer();
if (this.webImageInfo.IsLossless)
{
var losslessDecoder = new WebpLosslessDecoder(this.webImageInfo.Vp8LBitReader, this.memoryAllocator, this.Configuration);
losslessDecoder.Decode(pixels, image.Width, image.Height);
}
else
{
var lossyDecoder = new WebpLossyDecoder(this.webImageInfo.Vp8BitReader, this.memoryAllocator, this.Configuration);
lossyDecoder.Decode(pixels, image.Width, image.Height, this.webImageInfo);
}
return image;
// There can be optional chunks after the image data, like EXIF and XMP.
if (this.webImageInfo.Features != null)
{
this.ParseOptionalChunks(this.webImageInfo.Features);
}
return image;
}
}
catch
{
image?.Dispose();
throw;
}
}

1
tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs

@ -20,6 +20,7 @@ using static SixLabors.ImageSharp.Tests.TestImages.Bmp;
namespace SixLabors.ImageSharp.Tests.Formats.Bmp
{
[Trait("Format", "Bmp")]
[ValidateDisposedMemoryAllocations]
public class BmpDecoderTests
{
public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector;

1
tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs

@ -18,6 +18,7 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.Gif
{
[Trait("Format", "Gif")]
[ValidateDisposedMemoryAllocations]
public class GifDecoderTests
{
private const PixelTypes TestPixelTypes = PixelTypes.Rgba32 | PixelTypes.RgbaVector | PixelTypes.Argb32;

15
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs

@ -179,11 +179,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
IImageInfo imageInfo = useIdentify
? ((IImageInfoDetector)decoder).Identify(Configuration.Default, stream, default)
: decoder.Decode<Rgba32>(Configuration.Default, stream, default);
test(imageInfo);
if (useIdentify)
{
IImageInfo imageInfo = ((IImageInfoDetector)decoder).Identify(Configuration.Default, stream, default);
test(imageInfo);
}
else
{
using var img = decoder.Decode<Rgba32>(Configuration.Default, stream, default);
test(img);
}
}
}

1
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

@ -22,6 +22,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{
// TODO: Scatter test cases into multiple test classes
[Trait("Format", "Jpg")]
[ValidateDisposedMemoryAllocations]
public partial class JpegDecoderTests
{
public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.Bgr24 | PixelTypes.RgbaVector;

1
tests/ImageSharp.Tests/Formats/Pbm/PbmDecoderTests.cs

@ -11,6 +11,7 @@ using static SixLabors.ImageSharp.Tests.TestImages.Pbm;
namespace SixLabors.ImageSharp.Tests.Formats.Pbm
{
[Trait("Format", "Pbm")]
[ValidateDisposedMemoryAllocations]
public class PbmDecoderTests
{
[Theory]

2
tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs

@ -19,6 +19,7 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.Png
{
[Trait("Format", "Png")]
[ValidateDisposedMemoryAllocations]
public partial class PngDecoderTests
{
private const PixelTypes TestPixelTypes = PixelTypes.Rgba32 | PixelTypes.RgbaVector | PixelTypes.Argb32;
@ -103,7 +104,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
[Theory]
[WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32)]
[ValidateDisposedMemoryAllocations]
public void Decode<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{

1
tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs

@ -16,6 +16,7 @@ using static SixLabors.ImageSharp.Tests.TestImages.Tga;
namespace SixLabors.ImageSharp.Tests.Formats.Tga
{
[Trait("Format", "Tga")]
[ValidateDisposedMemoryAllocations]
public class TgaDecoderTests
{
private static TgaDecoder TgaDecoder => new();

1
tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs

@ -14,6 +14,7 @@ using static SixLabors.ImageSharp.Tests.TestImages.Tiff;
namespace SixLabors.ImageSharp.Tests.Formats.Tiff
{
[Trait("Format", "Tiff")]
[ValidateDisposedMemoryAllocations]
public class TiffDecoderTests : TiffDecoderBaseTester
{
public static readonly string[] MultiframeTestImages = Multiframes;

1
tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs

@ -13,6 +13,7 @@ using static SixLabors.ImageSharp.Tests.TestImages.Webp;
namespace SixLabors.ImageSharp.Tests.Formats.Webp
{
[Trait("Format", "Webp")]
[ValidateDisposedMemoryAllocations]
public class WebpDecoderTests
{
private static WebpDecoder WebpDecoder => new();

2
tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparingUtils.cs

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
}
var testFile = TestFile.Create(path);
Image<Rgba32> magickImage = DecodeWithMagick<Rgba32>(new FileInfo(testFile.FullPath));
using Image<Rgba32> magickImage = DecodeWithMagick<Rgba32>(new FileInfo(testFile.FullPath));
if (useExactComparer)
{
ImageComparer.Exact.VerifySimilarity(magickImage, image);

Loading…
Cancel
Save