Release owned Squeeze buffers and failed PPMd models

This commit is contained in:
Adam Hathcock
2026-10-13 10:24:19 +01:00
parent 46437bbbbc
commit b3fac7e04a
4 changed files with 102 additions and 21 deletions

View File

@@ -28,7 +28,16 @@ public class PpmdStream : Stream, IAsyncDisposable
_stream = stream;
_compress = compress;
InitializeSync(stream, compress);
try
{
InitializeSync(stream, compress);
}
catch
{
// Construction has not transferred ownership to a caller yet.
_modelH?.Dispose();
throw;
}
}
private PpmdStream(
@@ -47,6 +56,13 @@ public class PpmdStream : Stream, IAsyncDisposable
private void InitializeSync(Stream stream, bool compress)
{
if (
compress
&& (_properties.Version == PpmdVersion.H || _properties.Version == PpmdVersion.H7Z)
)
{
throw new NotImplementedException("PPMd H/H7Z compression not supported");
}
if (_properties.Version == PpmdVersion.I1)
{
_model = new Model();
@@ -62,19 +78,11 @@ public class PpmdStream : Stream, IAsyncDisposable
if (_properties.Version == PpmdVersion.H)
{
_modelH = new ModelPpm();
if (compress)
{
throw new NotImplementedException();
}
_modelH.DecodeInit(stream, _properties.ModelOrder, _properties.AllocatorSize);
}
if (_properties.Version == PpmdVersion.H7Z)
{
_modelH = new ModelPpm();
if (compress)
{
throw new NotImplementedException();
}
_modelH.DecodeInit(null, _properties.ModelOrder, _properties.AllocatorSize);
_decoder = new Decoder();
_decoder.Init(stream);

View File

@@ -17,11 +17,20 @@ public partial class SqueezeStream
)
{
var squeezeStream = new SqueezeStream(stream, compressedSize);
squeezeStream._decodedStream = await squeezeStream
.BuildDecodedStreamAsync(cancellationToken)
.ConfigureAwait(false);
return squeezeStream;
try
{
squeezeStream._decodedStream = await squeezeStream
.BuildDecodedStreamAsync(cancellationToken)
.ConfigureAwait(false);
return squeezeStream;
}
catch
{
#pragma warning disable VSTHRD103 // Cleanup only releases in-memory buffers; the source remains open.
squeezeStream.Dispose();
#pragma warning restore VSTHRD103
throw;
}
}
public override async Task<int> ReadAsync(
@@ -83,7 +92,7 @@ public partial class SqueezeStream
}
var bitReader = new BitReader(_stream);
var huffmanDecoded = new PooledMemoryStream();
var huffmanDecoded = _huffmanDecoded = new PooledMemoryStream();
int i = 0;
while (true)

View File

@@ -16,6 +16,7 @@ public partial class SqueezeStream : Stream
private const int SPEOF = 256;
private Stream _decodedStream = null!;
private PooledMemoryStream? _huffmanDecoded;
private SqueezeStream(Stream stream, int compressedSize)
{
@@ -25,15 +26,36 @@ public partial class SqueezeStream : Stream
public static SqueezeStream Create(Stream stream, int compressedSize)
{
var squeezeStream = new SqueezeStream(stream, compressedSize);
squeezeStream._decodedStream = squeezeStream.BuildDecodedStream();
return squeezeStream;
try
{
squeezeStream._decodedStream = squeezeStream.BuildDecodedStream();
return squeezeStream;
}
catch
{
squeezeStream.Dispose();
throw;
}
}
protected override void Dispose(bool disposing)
{
_decodedStream?.Dispose();
base.Dispose(disposing);
try
{
if (disposing)
{
_decodedStream?.Dispose();
}
}
finally
{
if (disposing)
{
// RunLength90Stream deliberately does not own its input.
_huffmanDecoded?.Dispose();
}
base.Dispose(disposing);
}
}
public override bool CanRead => true;
@@ -79,7 +101,7 @@ public partial class SqueezeStream : Stream
}
var bitReader = new BitReader(_stream);
var huffmanDecoded = new PooledMemoryStream();
var huffmanDecoded = _huffmanDecoded = new PooledMemoryStream();
int i = 0;
while (true)