Browse Source

check disposed buffers for decoders

pull/2082/head
Scott Williams 5 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) public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Image<TPixel> image = null;
try try
{ {
int bytesPerColorMapEntry = this.ReadImageHeaders(stream, out bool inverted, out byte[] palette); 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(); Buffer2D<TPixel> pixels = image.GetRootFramePixelBuffer();
@ -193,8 +194,14 @@ namespace SixLabors.ImageSharp.Formats.Bmp
} }
catch (IndexOutOfRangeException e) catch (IndexOutOfRangeException e)
{ {
image?.Dispose();
throw new ImageFormatException("Bitmap does not have a valid format.", e); throw new ImageFormatException("Bitmap does not have a valid format.", e);
} }
catch
{
image?.Dispose();
throw;
}
} }
/// <inheritdoc /> /// <inheritdoc />

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

@ -151,6 +151,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
} }
} }
} }
//catch
//{
// image?.Dispose();
// throw;
//}
finally finally
{ {
this.globalColorTable?.Dispose(); 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); jpegDecoder.ParseStream(stream, scanDecoderGray, CancellationToken.None);
// TODO: Should we pass through the CancellationToken from the tiff decoder? // 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; break;
} }
@ -81,7 +82,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors
jpegDecoder.ParseStream(stream, scanDecoder, CancellationToken.None); jpegDecoder.ParseStream(stream, scanDecoder, CancellationToken.None);
// TODO: Should we pass through the CancellationToken from the tiff decoder? // 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; 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 stripOffsetsArray = (Array)tags.GetValueInternal(ExifTag.StripOffsets).GetValue();
var stripByteCountsArray = (Array)tags.GetValueInternal(ExifTag.StripByteCounts).GetValue(); var stripByteCountsArray = (Array)tags.GetValueInternal(ExifTag.StripByteCounts).GetValue();
IMemoryOwner<ulong> stripOffsetsMemory = this.ConvertNumbers(stripOffsetsArray, out Span<ulong> stripOffsets); using IMemoryOwner<ulong> stripOffsetsMemory = this.ConvertNumbers(stripOffsetsArray, out Span<ulong> stripOffsets);
IMemoryOwner<ulong> stripByteCountsMemory = this.ConvertNumbers(stripByteCountsArray, out Span<ulong> stripByteCounts); using IMemoryOwner<ulong> stripByteCountsMemory = this.ConvertNumbers(stripByteCountsArray, out Span<ulong> stripByteCounts);
if (this.PlanarConfiguration == TiffPlanarConfiguration.Planar) if (this.PlanarConfiguration == TiffPlanarConfiguration.Planar)
{ {
@ -262,8 +262,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
cancellationToken); cancellationToken);
} }
stripOffsetsMemory?.Dispose();
stripByteCountsMemory?.Dispose();
return frame; 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) public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
this.Metadata = new ImageMetadata(); Image<TPixel> image = null;
this.currentStream = stream; try
{
uint fileSize = this.ReadImageHeader(); this.Metadata = new ImageMetadata();
this.currentStream = stream;
using (this.webImageInfo = this.ReadVp8Info()) uint fileSize = this.ReadImageHeader();
{
if (this.webImageInfo.Features is { Animation: true })
{
WebpThrowHelper.ThrowNotSupportedException("Animations are not supported");
}
var image = new Image<TPixel>(this.Configuration, (int)this.webImageInfo.Width, (int)this.webImageInfo.Height, this.Metadata); using (this.webImageInfo = this.ReadVp8Info())
Buffer2D<TPixel> pixels = image.GetRootFramePixelBuffer();
if (this.webImageInfo.IsLossless)
{ {
var losslessDecoder = new WebpLosslessDecoder(this.webImageInfo.Vp8LBitReader, this.memoryAllocator, this.Configuration); if (this.webImageInfo.Features is { Animation: true })
losslessDecoder.Decode(pixels, image.Width, image.Height); {
} WebpThrowHelper.ThrowNotSupportedException("Animations are not supported");
else }
{
var lossyDecoder = new WebpLossyDecoder(this.webImageInfo.Vp8BitReader, this.memoryAllocator, this.Configuration);
lossyDecoder.Decode(pixels, image.Width, image.Height, this.webImageInfo);
}
// There can be optional chunks after the image data, like EXIF and XMP. image = new Image<TPixel>(this.Configuration, (int)this.webImageInfo.Width, (int)this.webImageInfo.Height, this.Metadata);
if (this.webImageInfo.Features != null) Buffer2D<TPixel> pixels = image.GetRootFramePixelBuffer();
{ if (this.webImageInfo.IsLossless)
this.ParseOptionalChunks(this.webImageInfo.Features); {
} 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 namespace SixLabors.ImageSharp.Tests.Formats.Bmp
{ {
[Trait("Format", "Bmp")] [Trait("Format", "Bmp")]
[ValidateDisposedMemoryAllocations]
public class BmpDecoderTests public class BmpDecoderTests
{ {
public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector; 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 namespace SixLabors.ImageSharp.Tests.Formats.Gif
{ {
[Trait("Format", "Gif")] [Trait("Format", "Gif")]
[ValidateDisposedMemoryAllocations]
public class GifDecoderTests public class GifDecoderTests
{ {
private const PixelTypes TestPixelTypes = PixelTypes.Rgba32 | PixelTypes.RgbaVector | PixelTypes.Argb32; 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); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using (var stream = new MemoryStream(testFile.Bytes, false))
{ {
IImageInfo imageInfo = useIdentify if (useIdentify)
? ((IImageInfoDetector)decoder).Identify(Configuration.Default, stream, default) {
: decoder.Decode<Rgba32>(Configuration.Default, stream, default); IImageInfo imageInfo = ((IImageInfoDetector)decoder).Identify(Configuration.Default, stream, default);
test(imageInfo);
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 // TODO: Scatter test cases into multiple test classes
[Trait("Format", "Jpg")] [Trait("Format", "Jpg")]
[ValidateDisposedMemoryAllocations]
public partial class JpegDecoderTests public partial class JpegDecoderTests
{ {
public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.Bgr24 | PixelTypes.RgbaVector; 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 namespace SixLabors.ImageSharp.Tests.Formats.Pbm
{ {
[Trait("Format", "Pbm")] [Trait("Format", "Pbm")]
[ValidateDisposedMemoryAllocations]
public class PbmDecoderTests public class PbmDecoderTests
{ {
[Theory] [Theory]

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

@ -19,6 +19,7 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.Png namespace SixLabors.ImageSharp.Tests.Formats.Png
{ {
[Trait("Format", "Png")] [Trait("Format", "Png")]
[ValidateDisposedMemoryAllocations]
public partial class PngDecoderTests public partial class PngDecoderTests
{ {
private const PixelTypes TestPixelTypes = PixelTypes.Rgba32 | PixelTypes.RgbaVector | PixelTypes.Argb32; private const PixelTypes TestPixelTypes = PixelTypes.Rgba32 | PixelTypes.RgbaVector | PixelTypes.Argb32;
@ -103,7 +104,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
[Theory] [Theory]
[WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32)] [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32)]
[ValidateDisposedMemoryAllocations]
public void Decode<TPixel>(TestImageProvider<TPixel> provider) public void Decode<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> 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 namespace SixLabors.ImageSharp.Tests.Formats.Tga
{ {
[Trait("Format", "Tga")] [Trait("Format", "Tga")]
[ValidateDisposedMemoryAllocations]
public class TgaDecoderTests public class TgaDecoderTests
{ {
private static TgaDecoder TgaDecoder => new(); 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 namespace SixLabors.ImageSharp.Tests.Formats.Tiff
{ {
[Trait("Format", "Tiff")] [Trait("Format", "Tiff")]
[ValidateDisposedMemoryAllocations]
public class TiffDecoderTests : TiffDecoderBaseTester public class TiffDecoderTests : TiffDecoderBaseTester
{ {
public static readonly string[] MultiframeTestImages = Multiframes; 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 namespace SixLabors.ImageSharp.Tests.Formats.Webp
{ {
[Trait("Format", "Webp")] [Trait("Format", "Webp")]
[ValidateDisposedMemoryAllocations]
public class WebpDecoderTests public class WebpDecoderTests
{ {
private static WebpDecoder WebpDecoder => new(); 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); 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) if (useExactComparer)
{ {
ImageComparer.Exact.VerifySimilarity(magickImage, image); ImageComparer.Exact.VerifySimilarity(magickImage, image);

Loading…
Cancel
Save