64bit DataDescriptor

This commit is contained in:
Lars Vahlenberg
2022-08-04 21:22:31 +02:00
parent 3009e6dcfd
commit 44a5433af3
5 changed files with 72 additions and 11 deletions

View File

@@ -47,6 +47,9 @@ namespace SharpCompress.Common.Zip
{
_decompressionStream.Skip();
// If we had TotalIn / TotalOut we could have used them
Header.CompressedSize = _decompressionStream.Position;
if (_decompressionStream is DeflateStream deflateStream)
{
rewindableStream.Rewind(deflateStream.InputBuffer);
@@ -66,12 +69,26 @@ namespace SharpCompress.Common.Zip
br.ReadUInt32(); // CRC32
var compressed_size = br.ReadUInt32();
var uncompressed_size = br.ReadUInt32();
if (compressed_size == size && compressed_size == uncompressed_size )
var uncompressed_64bit = br.ReadInt64();
long test_64bit = (long)uncompressed_size << 32 | (long)compressed_size;
if( test_64bit == size && test_64bit == uncompressed_64bit )
{
rewindableStream.Position -= 16;
Header.CompressedSize = test_64bit;
Header.UncompressedSize = uncompressed_64bit;
rewindableStream.Position -= 24;
break;
}
rewindableStream.Position -= 12;
if (compressed_size == size && compressed_size == uncompressed_size )
{
Header.CompressedSize = compressed_size;
Header.UncompressedSize = uncompressed_size;
rewindableStream.Position -= 24;
break;
}
rewindableStream.Position -= 20;
}
}

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Common.Zip.Headers;
using SharpCompress.IO;
@@ -28,6 +28,7 @@ namespace SharpCompress.Common.Zip
{
ZipHeader? header;
BinaryReader reader = new BinaryReader(rewindableStream);
uint headerBytes = 0;
if (_lastEntryHeader != null &&
(FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor) || _lastEntryHeader.IsZip64))
{
@@ -39,15 +40,37 @@ namespace SharpCompress.Common.Zip
crc = reader.ReadUInt32();
}
_lastEntryHeader.Crc = crc;
_lastEntryHeader.CompressedSize = reader.ReadUInt32();
_lastEntryHeader.UncompressedSize = reader.ReadUInt32();
// The DataDescriptor can be either 64bit or 32bit
var compressed_size = reader.ReadUInt32();
var uncompressed_size = reader.ReadUInt32();
// Check if we have header or 64bit DataDescriptor
headerBytes = reader.ReadUInt32();
bool test_header = !(headerBytes == 0x04034b50 || headerBytes == 0x02014b50);
long test_64bit = (long)uncompressed_size << 32 | (long)compressed_size;
if ( test_64bit == _lastEntryHeader.CompressedSize && test_header )
{
_lastEntryHeader.UncompressedSize = (long)reader.ReadUInt32() << 32 | (long)headerBytes;
headerBytes = reader.ReadUInt32();
}
else
{
_lastEntryHeader.UncompressedSize = uncompressed_size;
}
if (pos.HasValue)
{
_lastEntryHeader.DataStartPosition = pos - _lastEntryHeader.CompressedSize;
}
}
else
{
headerBytes = reader.ReadUInt32();
}
_lastEntryHeader = null;
uint headerBytes = reader.ReadUInt32();
header = ReadHeader(headerBytes, reader);
if (header is null)
{
@@ -86,4 +109,4 @@ namespace SharpCompress.Common.Zip
}
}
}
}
}

View File

@@ -143,9 +143,11 @@ namespace SharpCompress.IO
if (!IsVolumes && count != 0 && Current.Position == Current.Length)
{
_prevSize += Current.Length;
var length = Current.Length;
if (!SetStream(_stream + 1)) //will load next file if present
break;
_prevSize += length;
Current.Seek(0, SeekOrigin.Begin);
}
}

View File

@@ -401,8 +401,6 @@ namespace SharpCompress.Test.Zip
}
}
[Fact]
public void Zip_Uncompressed_Skip_All()
{
@@ -415,5 +413,26 @@ namespace SharpCompress.Test.Zip
}
}
}
[Fact]
public void Zip_Uncompressed_64bit()
{
var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "64bitstream.zip.7z");
using (var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read))
{
var archive = Archives.ArchiveFactory.Open(stream);
var reader = archive.ExtractAllEntries();
reader.MoveToNextEntry();
var zipReader = ZipReader.Open(reader.OpenEntryStream());
var x = 0;
while (zipReader.MoveToNextEntry())
{
x++;
}
Assert.Equal(4, x);
}
}
}
}

Binary file not shown.