mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-11-15 17:02:03 +00:00
Reject truncated LZMA2 headers and prevent stalled decoding
This commit is contained in:
@@ -201,6 +201,11 @@ public partial class LzmaStream
|
||||
}
|
||||
}
|
||||
|
||||
if (_availableBytes < 0)
|
||||
{
|
||||
throw new DataErrorException();
|
||||
}
|
||||
|
||||
var toProcess = count - total;
|
||||
if (toProcess > _availableBytes)
|
||||
{
|
||||
@@ -224,6 +229,10 @@ public partial class LzmaStream
|
||||
}
|
||||
|
||||
var read = _outWindow.Read(buffer, offset, toProcess);
|
||||
if (read == 0 && _availableBytes > 0)
|
||||
{
|
||||
throw new DataErrorException();
|
||||
}
|
||||
total += read;
|
||||
offset += read;
|
||||
_position += read;
|
||||
@@ -317,6 +326,11 @@ public partial class LzmaStream
|
||||
}
|
||||
}
|
||||
|
||||
if (_availableBytes < 0)
|
||||
{
|
||||
throw new DataErrorException();
|
||||
}
|
||||
|
||||
var toProcess = count - total;
|
||||
if (toProcess > _availableBytes)
|
||||
{
|
||||
@@ -340,6 +354,10 @@ public partial class LzmaStream
|
||||
}
|
||||
|
||||
var read = _outWindow.Read(buffer, offset, toProcess);
|
||||
if (read == 0 && _availableBytes > 0)
|
||||
{
|
||||
throw new DataErrorException();
|
||||
}
|
||||
total += read;
|
||||
offset += read;
|
||||
_position += read;
|
||||
|
||||
@@ -266,6 +266,11 @@ public partial class LzmaStream : Stream, IStreamStack, IAsyncDisposable
|
||||
}
|
||||
}
|
||||
|
||||
if (_availableBytes < 0)
|
||||
{
|
||||
throw new DataErrorException();
|
||||
}
|
||||
|
||||
var toProcess = count - total;
|
||||
if (toProcess > _availableBytes)
|
||||
{
|
||||
@@ -283,6 +288,11 @@ public partial class LzmaStream : Stream, IStreamStack, IAsyncDisposable
|
||||
}
|
||||
|
||||
var read = _outWindow.Read(buffer, offset, toProcess);
|
||||
// Unknown-size raw LZMA can end without output; otherwise no progress is corruption.
|
||||
if (read == 0 && _availableBytes > 0)
|
||||
{
|
||||
throw new DataErrorException();
|
||||
}
|
||||
total += read;
|
||||
offset += read;
|
||||
_position += read;
|
||||
@@ -416,10 +426,21 @@ public partial class LzmaStream : Stream, IStreamStack, IAsyncDisposable
|
||||
return value;
|
||||
}
|
||||
|
||||
private int ReadChunkHeaderByte()
|
||||
{
|
||||
var value = _inputStream!.ReadByte();
|
||||
// EOF is not an LZMA2 end marker and must never enter chunk-size arithmetic.
|
||||
if (value < 0)
|
||||
{
|
||||
throw new DataErrorException();
|
||||
}
|
||||
_inputPosition++;
|
||||
return value;
|
||||
}
|
||||
|
||||
private void DecodeChunkHeader()
|
||||
{
|
||||
var control = _inputStream!.ReadByte();
|
||||
_inputPosition++;
|
||||
var control = ReadChunkHeaderByte();
|
||||
|
||||
if (control == 0x00)
|
||||
{
|
||||
@@ -448,17 +469,14 @@ public partial class LzmaStream : Stream, IStreamStack, IAsyncDisposable
|
||||
_uncompressedChunk = false;
|
||||
|
||||
_availableBytes = (control & 0x1F) << 16;
|
||||
_availableBytes += (_inputStream.ReadByte() << 8) + _inputStream.ReadByte() + 1;
|
||||
_inputPosition += 2;
|
||||
_availableBytes += (ReadChunkHeaderByte() << 8) + ReadChunkHeaderByte() + 1;
|
||||
|
||||
_rangeDecoderLimit = (_inputStream.ReadByte() << 8) + _inputStream.ReadByte() + 1;
|
||||
_inputPosition += 2;
|
||||
_rangeDecoderLimit = (ReadChunkHeaderByte() << 8) + ReadChunkHeaderByte() + 1;
|
||||
|
||||
if (control >= 0xC0)
|
||||
{
|
||||
_needProps = false;
|
||||
Properties[0] = (byte)_inputStream.ReadByte();
|
||||
_inputPosition++;
|
||||
Properties[0] = (byte)ReadChunkHeaderByte();
|
||||
|
||||
_decoder = new Decoder();
|
||||
_decoder.SetDecoderProperties(Properties);
|
||||
@@ -482,8 +500,7 @@ public partial class LzmaStream : Stream, IStreamStack, IAsyncDisposable
|
||||
else
|
||||
{
|
||||
_uncompressedChunk = true;
|
||||
_availableBytes = (_inputStream.ReadByte() << 8) + _inputStream.ReadByte() + 1;
|
||||
_inputPosition += 2;
|
||||
_availableBytes = (ReadChunkHeaderByte() << 8) + ReadChunkHeaderByte() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user