mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-11-15 17:02:03 +00:00
Skip ZIP64 extensible data without size-driven allocations
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.IO;
|
||||
@@ -8,7 +9,9 @@ internal partial class Zip64DirectoryEndHeader
|
||||
{
|
||||
internal override async ValueTask Read(AsyncBinaryReader reader)
|
||||
{
|
||||
SizeOfDirectoryEndRecord = (long)await reader.ReadUInt64Async().ConfigureAwait(false);
|
||||
SizeOfDirectoryEndRecord = ValidateRecordSize(
|
||||
await reader.ReadUInt64Async().ConfigureAwait(false)
|
||||
);
|
||||
VersionMadeBy = await reader.ReadUInt16Async().ConfigureAwait(false);
|
||||
VersionNeededToExtract = await reader.ReadUInt16Async().ConfigureAwait(false);
|
||||
VolumeNumber = await reader.ReadUInt32Async().ConfigureAwait(false);
|
||||
@@ -18,10 +21,14 @@ internal partial class Zip64DirectoryEndHeader
|
||||
DirectorySize = (long)await reader.ReadUInt64Async().ConfigureAwait(false);
|
||||
DirectoryStartOffsetRelativeToDisk = (long)
|
||||
await reader.ReadUInt64Async().ConfigureAwait(false);
|
||||
var size = (int)(
|
||||
SizeOfDirectoryEndRecord - SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS
|
||||
);
|
||||
DataSector = new byte[size];
|
||||
await reader.ReadBytesAsync(DataSector, 0, size).ConfigureAwait(false);
|
||||
var remaining =
|
||||
SizeOfDirectoryEndRecord - SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS;
|
||||
var buffer = new byte[4096];
|
||||
while (remaining > 0)
|
||||
{
|
||||
var size = (int)Math.Min(buffer.Length, remaining);
|
||||
await reader.ReadBytesAsync(buffer, 0, size).ConfigureAwait(false);
|
||||
remaining -= size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace SharpCompress.Common.Zip.Headers;
|
||||
@@ -9,7 +10,7 @@ internal partial class Zip64DirectoryEndHeader : ZipHeader
|
||||
|
||||
internal override void Read(BinaryReader reader)
|
||||
{
|
||||
SizeOfDirectoryEndRecord = (long)reader.ReadUInt64();
|
||||
SizeOfDirectoryEndRecord = ValidateRecordSize(reader.ReadUInt64());
|
||||
VersionMadeBy = reader.ReadUInt16();
|
||||
VersionNeededToExtract = reader.ReadUInt16();
|
||||
VolumeNumber = reader.ReadUInt32();
|
||||
@@ -18,12 +19,31 @@ internal partial class Zip64DirectoryEndHeader : ZipHeader
|
||||
TotalNumberOfEntries = (long)reader.ReadUInt64();
|
||||
DirectorySize = (long)reader.ReadUInt64();
|
||||
DirectoryStartOffsetRelativeToDisk = (long)reader.ReadUInt64();
|
||||
DataSector = reader.ReadBytes(
|
||||
(int)(
|
||||
SizeOfDirectoryEndRecord
|
||||
- SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS
|
||||
)
|
||||
);
|
||||
// Extensible data is not interpreted. Consume it without allocating from its declared size.
|
||||
var remaining =
|
||||
SizeOfDirectoryEndRecord - SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS;
|
||||
var buffer = new byte[4096];
|
||||
while (remaining > 0)
|
||||
{
|
||||
var read = reader.Read(buffer, 0, (int)Math.Min(buffer.Length, remaining));
|
||||
if (read == 0)
|
||||
{
|
||||
throw new IncompleteArchiveException("Truncated ZIP64 extensible data.");
|
||||
}
|
||||
remaining -= read;
|
||||
}
|
||||
}
|
||||
|
||||
private static long ValidateRecordSize(ulong size)
|
||||
{
|
||||
if (
|
||||
size < SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS
|
||||
|| size > long.MaxValue
|
||||
)
|
||||
{
|
||||
throw new InvalidFormatException("Invalid ZIP64 end record size.");
|
||||
}
|
||||
return (long)size;
|
||||
}
|
||||
|
||||
private const int SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS = 44;
|
||||
@@ -45,6 +65,4 @@ internal partial class Zip64DirectoryEndHeader : ZipHeader
|
||||
public long DirectorySize { get; private set; }
|
||||
|
||||
public long DirectoryStartOffsetRelativeToDisk { get; private set; }
|
||||
|
||||
public byte[]? DataSector { get; private set; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user