From b7b78edaa311ad25409092d1168e25f4a99799d1 Mon Sep 17 00:00:00 2001 From: Pat Hartl Date: Sat, 22 Jun 2024 00:09:25 -0500 Subject: [PATCH 1/4] Fixed extractions after first ZIP64 entry is read from stream --- .../Common/Zip/StreamingZipHeaderFactory.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index c0af5408..c165211e 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -49,7 +49,17 @@ internal IEnumerable ReadStreamHeader(Stream stream) 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 lastModifiedTime = reader.ReadUInt16(); + var lastModifiedDate = reader.ReadUInt16(); + var crc = reader.ReadUInt32(); if (crc == POST_DATA_DESCRIPTOR) { @@ -62,7 +72,6 @@ ref rewindableStream var uncompressed_size = reader.ReadUInt32(); // Check if we have header or 64bit DataDescriptor - headerBytes = reader.ReadUInt32(); var test_header = !(headerBytes == 0x04034b50 || headerBytes == 0x02014b50); var test_64bit = ((long)uncompressed_size << 32) | compressed_size; @@ -80,6 +89,9 @@ ref rewindableStream 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 From eee518b7fad11f04b1bc8c0938f27e622ae7b14d Mon Sep 17 00:00:00 2001 From: Pat Hartl Date: Sun, 23 Jun 2024 22:29:33 -0500 Subject: [PATCH 2/4] Reworked ZIP64 handling to separate block The last commit made in this branch messed up some ZIP reading and caused a bunch of tests to fail. These changes branch off ZIP64 logic into its own block so that data is read correctly for 64 and non-64 entries. --- .../Common/Zip/StreamingZipHeaderFactory.cs | 52 ++++++++++++++++--- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index c165211e..6e786560 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -34,13 +34,7 @@ internal IEnumerable ReadStreamHeader(Stream stream) ZipHeader? header; var reader = new BinaryReader(rewindableStream); uint headerBytes = 0; - if ( - _lastEntryHeader != null - && ( - FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor) - || _lastEntryHeader.IsZip64 - ) - ) + if (_lastEntryHeader != null && FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor)) { if (_lastEntryHeader.Part is null) { @@ -52,15 +46,57 @@ ref rewindableStream var pos = rewindableStream.CanSeek ? (long?)rewindableStream.Position : null; + 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 + headerBytes = reader.ReadUInt32(); + 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; + } + } + 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 lastModifiedTime = reader.ReadUInt16(); var lastModifiedDate = reader.ReadUInt16(); + var lastModifiedTime = reader.ReadUInt16(); var crc = reader.ReadUInt32(); + if (crc == POST_DATA_DESCRIPTOR) { crc = reader.ReadUInt32(); From 9bc0a1d7c7fac9457abc6721a672dbc82bced811 Mon Sep 17 00:00:00 2001 From: Pat Hartl Date: Sun, 23 Jun 2024 22:30:34 -0500 Subject: [PATCH 3/4] Null reference checking Reorders this null reference check to avoid throwing a null reference exception. --- src/SharpCompress/Common/Zip/ZipHeaderFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs index 40fe178f..4c7c6a93 100644 --- a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs @@ -56,11 +56,11 @@ ArchiveEncoding archiveEncoding case POST_DATA_DESCRIPTOR: { if ( + _lastEntryHeader != null && FlagUtility.HasFlag( _lastEntryHeader.NotNull().Flags, HeaderFlags.UsePostDataDescriptor ) - && _lastEntryHeader != null ) { _lastEntryHeader.Crc = reader.ReadUInt32(); From b89de6caadc4c044737a7bc1ec5239729c15e899 Mon Sep 17 00:00:00 2001 From: Pat Hartl Date: Mon, 24 Jun 2024 17:19:53 -0500 Subject: [PATCH 4/4] Fix formatting --- .../Common/Zip/StreamingZipHeaderFactory.cs | 9 +++++++-- src/SharpCompress/Common/Zip/ZipHeaderFactory.cs | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index 6e786560..508dfd1a 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -34,7 +34,10 @@ internal IEnumerable ReadStreamHeader(Stream stream) ZipHeader? header; var reader = new BinaryReader(rewindableStream); uint headerBytes = 0; - if (_lastEntryHeader != null && FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor)) + if ( + _lastEntryHeader != null + && FlagUtility.HasFlag(_lastEntryHeader.Flags, HeaderFlags.UsePostDataDescriptor) + ) { if (_lastEntryHeader.Part is null) { @@ -83,7 +86,9 @@ ref rewindableStream if (_lastEntryHeader.Part is null) continue; - reader = ((StreamingZipFilePart)_lastEntryHeader.Part).FixStreamedFileLocation(ref rewindableStream); + reader = ((StreamingZipFilePart)_lastEntryHeader.Part).FixStreamedFileLocation( + ref rewindableStream + ); var pos = rewindableStream.CanSeek ? (long?)rewindableStream.Position : null; diff --git a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs index 4c7c6a93..45869ff6 100644 --- a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs @@ -56,8 +56,8 @@ ArchiveEncoding archiveEncoding case POST_DATA_DESCRIPTOR: { if ( - _lastEntryHeader != null && - FlagUtility.HasFlag( + _lastEntryHeader != null + && FlagUtility.HasFlag( _lastEntryHeader.NotNull().Flags, HeaderFlags.UsePostDataDescriptor )