Browse Source

ensure we dispose beffers when decoders throw

pull/2082/head
Scott Williams 4 years ago
parent
commit
2a1ae5cc4c
  1. 1
      src/Directory.Build.props
  2. 5
      src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs
  3. 35
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  4. 58
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

1
src/Directory.Build.props

@ -27,6 +27,7 @@
<InternalsVisibleTo Include="ImageSharp.Benchmarks" Key="$(SixLaborsPublicKey)" /> <InternalsVisibleTo Include="ImageSharp.Benchmarks" Key="$(SixLaborsPublicKey)" />
<InternalsVisibleTo Include="ImageSharp.Tests.ProfilingSandbox" Key="$(SixLaborsPublicKey)" /> <InternalsVisibleTo Include="ImageSharp.Tests.ProfilingSandbox" Key="$(SixLaborsPublicKey)" />
<InternalsVisibleTo Include="SixLabors.ImageSharp.Tests" Key="$(SixLaborsPublicKey)" /> <InternalsVisibleTo Include="SixLabors.ImageSharp.Tests" Key="$(SixLaborsPublicKey)" />
<InternalsVisibleTo Include="SixLabors.ImageSharp.Drawing.Tests" Key="$(SixLaborsPublicKey)" />
</ItemGroup> </ItemGroup>
</Project> </Project>

5
src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs

@ -95,7 +95,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
} }
} }
return this.pixelBuffer; var buffer = this.pixelBuffer;
this.pixelBuffer = null;
return buffer;
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -210,6 +212,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
this.rgbBuffer?.Dispose(); this.rgbBuffer?.Dispose();
this.paddedProxyPixelRow?.Dispose(); this.paddedProxyPixelRow?.Dispose();
this.pixelBuffer?.Dispose();
} }
} }
} }

35
src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

@ -187,20 +187,27 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
using var spectralConverter = new SpectralConverter<TPixel>(this.Configuration); using var spectralConverter = new SpectralConverter<TPixel>(this.Configuration);
try
var scanDecoder = new HuffmanScanDecoder(stream, spectralConverter, cancellationToken); {
var scanDecoder = new HuffmanScanDecoder(stream, spectralConverter, cancellationToken);
this.ParseStream(stream, scanDecoder, cancellationToken);
this.InitExifProfile(); this.ParseStream(stream, scanDecoder, cancellationToken);
this.InitIccProfile(); this.InitExifProfile();
this.InitIptcProfile(); this.InitIccProfile();
this.InitXmpProfile(); this.InitIptcProfile();
this.InitDerivedMetadataProperties(); this.InitXmpProfile();
this.InitDerivedMetadataProperties();
return new Image<TPixel>(
this.Configuration, return new Image<TPixel>(
spectralConverter.GetPixelBuffer(cancellationToken), this.Configuration,
this.Metadata); spectralConverter.GetPixelBuffer(cancellationToken),
this.Metadata);
}
catch
{
this.Frame?.Dispose();
throw;
}
} }
/// <inheritdoc/> /// <inheritdoc/>

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

@ -157,40 +157,52 @@ namespace SixLabors.ImageSharp.Formats.Tiff
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.inputStream = stream;
var reader = new DirectoryReader(stream, this.Configuration.MemoryAllocator);
IEnumerable<ExifProfile> directories = reader.Read();
this.byteOrder = reader.ByteOrder;
this.isBigTiff = reader.IsBigTiff;
var frames = new List<ImageFrame<TPixel>>(); var frames = new List<ImageFrame<TPixel>>();
foreach (ExifProfile ifd in directories) try
{ {
cancellationToken.ThrowIfCancellationRequested(); this.inputStream = stream;
ImageFrame<TPixel> frame = this.DecodeFrame<TPixel>(ifd, cancellationToken); var reader = new DirectoryReader(stream, this.Configuration.MemoryAllocator);
frames.Add(frame);
IEnumerable<ExifProfile> directories = reader.Read();
this.byteOrder = reader.ByteOrder;
this.isBigTiff = reader.IsBigTiff;
if (this.decodingMode is FrameDecodingMode.First) foreach (ExifProfile ifd in directories)
{ {
break; cancellationToken.ThrowIfCancellationRequested();
ImageFrame<TPixel> frame = this.DecodeFrame<TPixel>(ifd, cancellationToken);
frames.Add(frame);
if (this.decodingMode is FrameDecodingMode.First)
{
break;
}
} }
}
ImageMetadata metadata = TiffDecoderMetadataCreator.Create(frames, this.ignoreMetadata, reader.ByteOrder, reader.IsBigTiff); ImageMetadata metadata = TiffDecoderMetadataCreator.Create(frames, this.ignoreMetadata, reader.ByteOrder, reader.IsBigTiff);
// TODO: Tiff frames can have different sizes. // TODO: Tiff frames can have different sizes.
ImageFrame<TPixel> root = frames[0]; ImageFrame<TPixel> root = frames[0];
this.Dimensions = root.Size(); this.Dimensions = root.Size();
foreach (ImageFrame<TPixel> frame in frames) foreach (ImageFrame<TPixel> frame in frames)
{
if (frame.Size() != root.Size())
{ {
TiffThrowHelper.ThrowNotSupported("Images with different sizes are not supported"); if (frame.Size() != root.Size())
{
TiffThrowHelper.ThrowNotSupported("Images with different sizes are not supported");
}
} }
return new Image<TPixel>(this.Configuration, metadata, frames);
} }
catch
{
foreach (ImageFrame<TPixel> f in frames)
{
f.Dispose();
}
return new Image<TPixel>(this.Configuration, metadata, frames); throw;
}
} }
/// <inheritdoc/> /// <inheritdoc/>

Loading…
Cancel
Save