Skip to content

Commit

Permalink
Merge pull request #852 from LANCommander/fix-post-zip64-entry-subseq…
Browse files Browse the repository at this point in the history
…uent-extractions

Fixed extractions after first ZIP64 entry is read from stream
  • Loading branch information
adamhathcock authored Jun 26, 2024
2 parents 3eaac68 + b89de6c commit d18cad6
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 6 deletions.
61 changes: 57 additions & 4 deletions src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ internal IEnumerable<ZipHeader> ReadStreamHeader(Stream stream)
uint headerBytes = 0;
if (
_lastEntryHeader != null
&& (
FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor)
|| _lastEntryHeader.IsZip64
)
&& FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor)
)
{
if (_lastEntryHeader.Part is null)
Expand All @@ -49,7 +46,9 @@ internal IEnumerable<ZipHeader> ReadStreamHeader(Stream stream)
reader = ((StreamingZipFilePart)_lastEntryHeader.Part).FixStreamedFileLocation(
ref rewindableStream
);

var pos = rewindableStream.CanSeek ? (long?)rewindableStream.Position : null;

var crc = reader.ReadUInt32();
if (crc == POST_DATA_DESCRIPTOR)
{
Expand Down Expand Up @@ -82,6 +81,60 @@ ref rewindableStream
_lastEntryHeader.DataStartPosition = pos - _lastEntryHeader.CompressedSize;
}
}
else if (_lastEntryHeader != null && _lastEntryHeader.IsZip64)
{
if (_lastEntryHeader.Part is null)
continue;

reader = ((StreamingZipFilePart)_lastEntryHeader.Part).FixStreamedFileLocation(
ref rewindableStream
);

var pos = rewindableStream.CanSeek ? (long?)rewindableStream.Position : null;

headerBytes = reader.ReadUInt32();

var version = reader.ReadUInt16();
var flags = (HeaderFlags)reader.ReadUInt16();
var compressionMethod = (ZipCompressionMethod)reader.ReadUInt16();
var lastModifiedDate = reader.ReadUInt16();
var lastModifiedTime = reader.ReadUInt16();

var crc = reader.ReadUInt32();

if (crc == POST_DATA_DESCRIPTOR)
{
crc = reader.ReadUInt32();
}
_lastEntryHeader.Crc = crc;

// 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
var test_header = !(headerBytes == 0x04034b50 || headerBytes == 0x02014b50);

var test_64bit = ((long)uncompressed_size << 32) | compressed_size;
if (test_64bit == _lastEntryHeader.CompressedSize && test_header)
{
_lastEntryHeader.UncompressedSize =
((long)reader.ReadUInt32() << 32) | headerBytes;
headerBytes = reader.ReadUInt32();
}
else
{
_lastEntryHeader.UncompressedSize = uncompressed_size;
}

if (pos.HasValue)
{
_lastEntryHeader.DataStartPosition = pos - _lastEntryHeader.CompressedSize;

// 4 = First 4 bytes of the entry header (i.e. 50 4B 03 04)
rewindableStream.Position = pos.Value + 4;
}
}
else
{
headerBytes = reader.ReadUInt32();
Expand Down
4 changes: 2 additions & 2 deletions src/SharpCompress/Common/Zip/ZipHeaderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ ArchiveEncoding archiveEncoding
case POST_DATA_DESCRIPTOR:
{
if (
FlagUtility.HasFlag(
_lastEntryHeader != null
&& FlagUtility.HasFlag(
_lastEntryHeader.NotNull().Flags,
HeaderFlags.UsePostDataDescriptor
)
&& _lastEntryHeader != null
)
{
_lastEntryHeader.Crc = reader.ReadUInt32();
Expand Down

0 comments on commit d18cad6

Please sign in to comment.