From 29eaa8443a10535f067dac1fff3ea094a0443c92 Mon Sep 17 00:00:00 2001 From: darkms Date: Mon, 28 Jan 2019 22:08:40 +0700 Subject: [PATCH 01/11] Bumped version --- .semver | 2 +- src/SolutionInfo.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.semver b/.semver index 8ae5023..bfe5145 100644 --- a/.semver +++ b/.semver @@ -1,6 +1,6 @@ --- :major: 1 :minor: 13 -:patch: 1 +:patch: 2 :special: '' :metadata: '' diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index 6895758..9e1f236 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -1,6 +1,6 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -[assembly: AssemblyVersion("1.13.1")] -[assembly: AssemblyFileVersion("1.13.1")] -[assembly: AssemblyInformationalVersion("1.13.1.000000")] +[assembly: AssemblyVersion("1.13.2")] +[assembly: AssemblyFileVersion("1.13.2")] +[assembly: AssemblyInformationalVersion("1.13.2.000000")] From 973e63c32d466e6f47925044fc6a1d2fb7effb32 Mon Sep 17 00:00:00 2001 From: Richard Webb Date: Tue, 19 Feb 2019 11:11:41 +0000 Subject: [PATCH 02/11] The gem --no-ri option seems to be removed, so try using --no-document instead --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 030dadb..5d4f50b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,7 +7,7 @@ - master install: - set PATH=C:\Ruby25\bin;%PATH% - - gem install bundler --no-ri --no-rdoc + - gem install bundler --no-document - bundle install build_script: - bundle exec rake @@ -24,7 +24,7 @@ - master install: - set PATH=C:\Ruby25\bin;%PATH% - - gem install bundler --no-ri --no-rdoc + - gem install bundler --no-document - bundle install build_script: - bundle exec rake From 6928e407f647ba69fc9c5e13c552bf5c0fee3f72 Mon Sep 17 00:00:00 2001 From: Richard Webb Date: Tue, 22 Jan 2019 17:37:47 +0000 Subject: [PATCH 03/11] In WinZipAesCipherStream, create the AES instance using 'Aes.Create()' instead of 'new AesManaged()' --- src/Zip.Shared/WinZipAes.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Zip.Shared/WinZipAes.cs b/src/Zip.Shared/WinZipAes.cs index c6bffb1..7445754 100644 --- a/src/Zip.Shared/WinZipAes.cs +++ b/src/Zip.Shared/WinZipAes.cs @@ -356,7 +356,7 @@ internal class WinZipAesCipherStream : Stream internal HMACSHA1 _mac; - internal AesManaged _aesCipher; + internal Aes _aesCipher; internal ICryptoTransform _xform; private const int BLOCK_SIZE_IN_BYTES = 16; @@ -428,7 +428,7 @@ internal WinZipAesCipherStream(System.IO.Stream s, WinZipAesCrypto cryptoParams, _mac = new HMACSHA1(_params.MacIv); - _aesCipher = new System.Security.Cryptography.AesManaged(); + _aesCipher = System.Security.Cryptography.Aes.Create(); _aesCipher.BlockSize = 128; _aesCipher.KeySize = keySizeInBits; // 128, 192, 256 _aesCipher.Mode = CipherMode.ECB; @@ -835,6 +835,9 @@ public override void Close() } _s.Close(); + _xform.Dispose(); + _aesCipher.Dispose(); + #if WANT_TRACE untransformed.Close(); transformed.Close(); From 4713be360fe7180e5cd509f6a5d9f899ad42c158 Mon Sep 17 00:00:00 2001 From: Richard Webb Date: Tue, 19 Feb 2019 10:37:37 +0000 Subject: [PATCH 04/11] Bump version --- .semver | 2 +- src/SolutionInfo.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.semver b/.semver index bfe5145..8a1ec70 100644 --- a/.semver +++ b/.semver @@ -1,6 +1,6 @@ --- :major: 1 :minor: 13 -:patch: 2 +:patch: 3 :special: '' :metadata: '' diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index 9e1f236..4a629f0 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -1,6 +1,6 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -[assembly: AssemblyVersion("1.13.2")] -[assembly: AssemblyFileVersion("1.13.2")] -[assembly: AssemblyInformationalVersion("1.13.2.000000")] +[assembly: AssemblyVersion("1.13.3")] +[assembly: AssemblyFileVersion("1.13.3")] +[assembly: AssemblyInformationalVersion("1.13.3.000000")] From 4da0640be960fdf5a07fcc235527caafa0f4219b Mon Sep 17 00:00:00 2001 From: darkms Date: Wed, 23 Oct 2019 19:48:51 +0700 Subject: [PATCH 05/11] Added tests for compatibility of Zip64 with WinZip and 7Zip --- src/Zip Tests/IonicTestClass.cs | 20 +++++++--- src/Zip Tests/SplitArchives.cs | 69 ++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/Zip Tests/IonicTestClass.cs b/src/Zip Tests/IonicTestClass.cs index 79d946c..2fc4cab 100644 --- a/src/Zip Tests/IonicTestClass.cs +++ b/src/Zip Tests/IonicTestClass.cs @@ -304,15 +304,23 @@ protected bool WinZipIsPresent { if (_WinZipIsPresent == null) { - string progfiles = null; - if (_wzunzip == null || _wzzip == null) + var programFilesRoots = new[] { - progfiles = System.Environment.GetEnvironmentVariable("ProgramFiles(x86)"); - _wzunzip = Path.Combine(progfiles, "winzip\\wzunzip.exe"); - _wzzip = Path.Combine(progfiles, "winzip\\wzzip.exe"); + System.Environment.GetEnvironmentVariable("ProgramFiles(x86)"), + System.Environment.GetEnvironmentVariable("ProgramW6432") + }; + foreach (var programFiles in programFilesRoots) + { + _wzunzip = Path.Combine(programFiles, "winzip\\wzunzip.exe"); + _wzzip = Path.Combine(programFiles, "winzip\\wzzip.exe"); + _WinZipIsPresent = File.Exists(_wzunzip) && File.Exists(_wzzip); + if (_WinZipIsPresent.Value) + { + break; + } } - _WinZipIsPresent = new Nullable(File.Exists(_wzunzip) && File.Exists(_wzzip)); } + return _WinZipIsPresent.Value; } } diff --git a/src/Zip Tests/SplitArchives.cs b/src/Zip Tests/SplitArchives.cs index bd8be44..f3b5f2a 100644 --- a/src/Zip Tests/SplitArchives.cs +++ b/src/Zip Tests/SplitArchives.cs @@ -722,6 +722,36 @@ public void Spanned_WinZip_Unzip_wi13691() } } + [TestMethod] + [Timeout(5 * 60 * 1000)] + public void Spanned_Zip64_WinZip_Unzip() + { + if (!WinZipIsPresent) + throw new Exception("winzip is not present"); + + Test_SpannedZip64_Unzip_Compatibility((zipFilePath, extractDir) => + { + var args = string.Format("-d -yx {0} \"{1}\"", + zipFilePath, extractDir); + Exec(wzunzip, args); + }); + } + + [TestMethod] + [Timeout(5 * 60 * 1000)] + public void Spanned_Zip64_7Zip_Unzip() + { + if (!SevenZipIsPresent) + throw new Exception("7-zip is not present"); + + Test_SpannedZip64_Unzip_Compatibility((zipFilePath, extractDir) => + { + var args = string.Format("x {0} -o\"{1}\"", + zipFilePath, extractDir); + Exec(sevenZip, args); + }); + } + #if INFOZIP_UNZIP_SUPPORTS_SPLIT_ARCHIVES @@ -881,10 +911,45 @@ public void Spanned_InfoZip_Zip_wi13691() Assert.AreEqual(filesToAdd.Count, filesUnzipped.Length, "Incorrect number of files extracted, trail {0}", k); } - } + private void Test_SpannedZip64_Unzip_Compatibility(Action unzipAction) + { + TestContext.WriteLine("Creating fodder files... {0}", + DateTime.Now.ToString("G")); + CreateSomeFiles(); + var filesToAdd = new List(Directory.GetFiles(_fodderDir)); + int[] segSizes = { 128, 256, 512 }; - } + for (int k = 0; k < segSizes.Length; k++) + { + string trialDir = String.Format("trial.{0}", k); + Directory.CreateDirectory(trialDir); + string zipFile1 = Path.Combine(trialDir, "InitialSave." + k + ".zip"); + TestContext.WriteLine(""); + TestContext.WriteLine("Creating zip... T({0})...{1}", + k, DateTime.Now.ToString("G")); + + using (var zip1 = new ZipFile()) + { + zip1.UseZip64WhenSaving = Zip64Option.Always; + + zip1.AddFiles(filesToAdd, ""); + zip1.MaxOutputSegmentSize = segSizes[k] * 1024; + zip1.Save(zipFile1); + } + TestContext.WriteLine(""); + TestContext.WriteLine("Extracting..."); + string extractDir = Path.Combine(trialDir, "extract"); + Directory.CreateDirectory(extractDir); + + unzipAction(zipFile1, extractDir); + + string[] filesUnzipped = Directory.GetFiles(extractDir); + Assert.AreEqual(filesToAdd.Count, filesUnzipped.Length, + "Incorrect number of files extracted, trail {0}", k); + } + } + } } From bd04dae9f1bb61153cd10975dba12ea080dba460 Mon Sep 17 00:00:00 2001 From: darkms Date: Wed, 23 Oct 2019 20:30:51 +0700 Subject: [PATCH 06/11] Bigger source files and span size --- src/Zip Tests/SplitArchives.cs | 61 +++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/src/Zip Tests/SplitArchives.cs b/src/Zip Tests/SplitArchives.cs index f3b5f2a..6388e7b 100644 --- a/src/Zip Tests/SplitArchives.cs +++ b/src/Zip Tests/SplitArchives.cs @@ -723,7 +723,7 @@ public void Spanned_WinZip_Unzip_wi13691() } [TestMethod] - [Timeout(5 * 60 * 1000)] + [Timeout(15 * 60 * 1000)] public void Spanned_Zip64_WinZip_Unzip() { if (!WinZipIsPresent) @@ -738,7 +738,7 @@ public void Spanned_Zip64_WinZip_Unzip() } [TestMethod] - [Timeout(5 * 60 * 1000)] + [Timeout(15 * 60 * 1000)] public void Spanned_Zip64_7Zip_Unzip() { if (!SevenZipIsPresent) @@ -748,7 +748,8 @@ public void Spanned_Zip64_7Zip_Unzip() { var args = string.Format("x {0} -o\"{1}\"", zipFilePath, extractDir); - Exec(sevenZip, args); + var output = Exec(sevenZip, args); + Assert.IsTrue(output.IndexOf("error", StringComparison.OrdinalIgnoreCase) == -1); }); } @@ -918,38 +919,44 @@ private void Test_SpannedZip64_Unzip_Compatibility(Action unzipA TestContext.WriteLine("Creating fodder files... {0}", DateTime.Now.ToString("G")); CreateSomeFiles(); - var filesToAdd = new List(Directory.GetFiles(_fodderDir)); - int[] segSizes = { 128, 256, 512 }; - for (int k = 0; k < segSizes.Length; k++) - { - string trialDir = String.Format("trial.{0}", k); - Directory.CreateDirectory(trialDir); - string zipFile1 = Path.Combine(trialDir, "InitialSave." + k + ".zip"); - TestContext.WriteLine(""); - TestContext.WriteLine("Creating zip... T({0})...{1}", - k, DateTime.Now.ToString("G")); + var file1Path = Path.Combine(_fodderDir, "1.dat"); + var file2Path = Path.Combine(_fodderDir, "2.dat"); - using (var zip1 = new ZipFile()) + foreach (var filePath in new[] { file1Path, file2Path }) + { + using (var file = File.Create(filePath)) { - zip1.UseZip64WhenSaving = Zip64Option.Always; - - zip1.AddFiles(filesToAdd, ""); - zip1.MaxOutputSegmentSize = segSizes[k] * 1024; - zip1.Save(zipFile1); + // 6GB files (over default non-Zip64 '4GB' limit) + file.Seek(6 * 1024 * 1024 * 1024L, SeekOrigin.Begin); + file.Write(new byte[] { 1 }, 0, 1); } + } - TestContext.WriteLine(""); - TestContext.WriteLine("Extracting..."); - string extractDir = Path.Combine(trialDir, "extract"); - Directory.CreateDirectory(extractDir); + Directory.CreateDirectory("zip-output"); + var zipFilePath = Path.Combine("zip-output", "archive.zip"); - unzipAction(zipFile1, extractDir); + using (var zipFile = new ZipFile()) + { + zipFile.UseZip64WhenSaving = Zip64Option.Always; + // disable compression to make sure out 0-filled files would keep their size + zipFile.CompressionLevel = Zlib.CompressionLevel.None; + // 5GB span (over default non-Zip64 '4GB' limit) + zipFile.MaxOutputSegmentSize64 = 5 * 1024 * 1024 * 1024L; - string[] filesUnzipped = Directory.GetFiles(extractDir); - Assert.AreEqual(filesToAdd.Count, filesUnzipped.Length, - "Incorrect number of files extracted, trail {0}", k); + zipFile.AddFile(file1Path, ""); + zipFile.AddFile(file2Path, ""); + + zipFile.Save(zipFilePath); } + + var extractDir = "extract"; + Directory.CreateDirectory(extractDir); + + unzipAction(zipFilePath, extractDir); + + string[] filesUnzipped = Directory.GetFiles(extractDir); + Assert.AreEqual(2, filesUnzipped.Length, "Incorrect number of files extracted"); } } } From 10c0b87fb6cc59ee234b020f40cf535be51cc70a Mon Sep 17 00:00:00 2001 From: darkms Date: Wed, 23 Oct 2019 20:41:30 +0700 Subject: [PATCH 07/11] Added tests for smaller files --- src/Zip Tests/SplitArchives.cs | 92 ++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 20 deletions(-) diff --git a/src/Zip Tests/SplitArchives.cs b/src/Zip Tests/SplitArchives.cs index 6388e7b..c82a5b9 100644 --- a/src/Zip Tests/SplitArchives.cs +++ b/src/Zip Tests/SplitArchives.cs @@ -724,33 +724,84 @@ public void Spanned_WinZip_Unzip_wi13691() [TestMethod] [Timeout(15 * 60 * 1000)] - public void Spanned_Zip64_WinZip_Unzip() + public void Spanned_Zip64_HugeFiles_WinZip_Unzip() { if (!WinZipIsPresent) throw new Exception("winzip is not present"); - Test_SpannedZip64_Unzip_Compatibility((zipFilePath, extractDir) => - { - var args = string.Format("-d -yx {0} \"{1}\"", - zipFilePath, extractDir); - Exec(wzunzip, args); - }); + Test_SpannedZip64_Unzip_Compatibility( + // 6GB files (over default non-Zip64 '4GB' limit) + 6 * 1024 * 1024 * 1024L, + // 5GB span (over default non-Zip64 '4GB' limit) + 5 * 1024 * 1024 * 1024L, + (zipFilePath, extractDir) => + { + var args = string.Format("-d -yx {0} \"{1}\"", + zipFilePath, extractDir); + Exec(wzunzip, args); + }); } [TestMethod] [Timeout(15 * 60 * 1000)] - public void Spanned_Zip64_7Zip_Unzip() + public void Spanned_Zip64_SmallFiles_WinZip_Unzip() + { + if (!WinZipIsPresent) + throw new Exception("winzip is not present"); + + Test_SpannedZip64_Unzip_Compatibility( + // 2MB files + 2 * 1024 * 1024L, + // 1MB span + 1 * 1024 * 1024L, + (zipFilePath, extractDir) => + { + var args = string.Format("-d -yx {0} \"{1}\"", + zipFilePath, extractDir); + Exec(wzunzip, args); + }); + } + + [TestMethod] + [Timeout(15 * 60 * 1000)] + public void Spanned_Zip64_HugeFiles_7Zip_Unzip() { if (!SevenZipIsPresent) throw new Exception("7-zip is not present"); - Test_SpannedZip64_Unzip_Compatibility((zipFilePath, extractDir) => - { - var args = string.Format("x {0} -o\"{1}\"", - zipFilePath, extractDir); - var output = Exec(sevenZip, args); - Assert.IsTrue(output.IndexOf("error", StringComparison.OrdinalIgnoreCase) == -1); - }); + Test_SpannedZip64_Unzip_Compatibility( + // 6GB files (over default non-Zip64 '4GB' limit) + 6 * 1024 * 1024 * 1024L, + // 5GB span (over default non-Zip64 '4GB' limit) + 5 * 1024 * 1024 * 1024L, + (zipFilePath, extractDir) => + { + var args = string.Format("x {0} -o\"{1}\"", + zipFilePath, extractDir); + var output = Exec(sevenZip, args); + Assert.IsTrue(output.IndexOf("error", StringComparison.OrdinalIgnoreCase) == -1); + }); + } + + [TestMethod] + [Timeout(15 * 60 * 1000)] + public void Spanned_Zip64_SmallFiles_7Zip_Unzip() + { + if (!SevenZipIsPresent) + throw new Exception("7-zip is not present"); + + Test_SpannedZip64_Unzip_Compatibility( + // 2MB files + 2 * 1024 * 1024L, + // 1MB span + 1 * 1024 * 1024L, + (zipFilePath, extractDir) => + { + var args = string.Format("x {0} -o\"{1}\"", + zipFilePath, extractDir); + var output = Exec(sevenZip, args); + Assert.IsTrue(output.IndexOf("error", StringComparison.OrdinalIgnoreCase) == -1); + }); } @@ -914,7 +965,10 @@ public void Spanned_InfoZip_Zip_wi13691() } } - private void Test_SpannedZip64_Unzip_Compatibility(Action unzipAction) + private void Test_SpannedZip64_Unzip_Compatibility( + long fileSize, + long spanSize, + Action unzipAction) { TestContext.WriteLine("Creating fodder files... {0}", DateTime.Now.ToString("G")); @@ -927,8 +981,7 @@ private void Test_SpannedZip64_Unzip_Compatibility(Action unzipA { using (var file = File.Create(filePath)) { - // 6GB files (over default non-Zip64 '4GB' limit) - file.Seek(6 * 1024 * 1024 * 1024L, SeekOrigin.Begin); + file.Seek(fileSize, SeekOrigin.Begin); file.Write(new byte[] { 1 }, 0, 1); } } @@ -941,8 +994,7 @@ private void Test_SpannedZip64_Unzip_Compatibility(Action unzipA zipFile.UseZip64WhenSaving = Zip64Option.Always; // disable compression to make sure out 0-filled files would keep their size zipFile.CompressionLevel = Zlib.CompressionLevel.None; - // 5GB span (over default non-Zip64 '4GB' limit) - zipFile.MaxOutputSegmentSize64 = 5 * 1024 * 1024 * 1024L; + zipFile.MaxOutputSegmentSize64 = spanSize; zipFile.AddFile(file1Path, ""); zipFile.AddFile(file2Path, ""); From 319d5dbed83898c3733f4aba097d3e8555827bd8 Mon Sep 17 00:00:00 2001 From: darkms Date: Wed, 23 Oct 2019 20:43:54 +0700 Subject: [PATCH 08/11] Added error output to test message --- src/Zip Tests/SplitArchives.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Zip Tests/SplitArchives.cs b/src/Zip Tests/SplitArchives.cs index c82a5b9..f2db8fc 100644 --- a/src/Zip Tests/SplitArchives.cs +++ b/src/Zip Tests/SplitArchives.cs @@ -779,7 +779,9 @@ public void Spanned_Zip64_HugeFiles_7Zip_Unzip() var args = string.Format("x {0} -o\"{1}\"", zipFilePath, extractDir); var output = Exec(sevenZip, args); - Assert.IsTrue(output.IndexOf("error", StringComparison.OrdinalIgnoreCase) == -1); + Assert.IsTrue( + output.IndexOf("error", StringComparison.OrdinalIgnoreCase) == -1, + "Output contains errors: " + output); }); } @@ -800,7 +802,9 @@ public void Spanned_Zip64_SmallFiles_7Zip_Unzip() var args = string.Format("x {0} -o\"{1}\"", zipFilePath, extractDir); var output = Exec(sevenZip, args); - Assert.IsTrue(output.IndexOf("error", StringComparison.OrdinalIgnoreCase) == -1); + Assert.IsTrue( + output.IndexOf("error", StringComparison.OrdinalIgnoreCase) == -1, + "Output contains errors: " + output); }); } From 7b005bef44c75f03c899dc206a8c7f293f7a6a57 Mon Sep 17 00:00:00 2001 From: darkms Date: Wed, 23 Oct 2019 20:57:21 +0700 Subject: [PATCH 09/11] Fixed Zip64 logic to set -1 to 'Relative Header' and 'Disk Start' in central directory when Zip64 extra is appended, also fixed disk number in Zip64 extra always being 0 --- src/Zip.Shared/ZipEntry.Write.cs | 80 +++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/src/Zip.Shared/ZipEntry.Write.cs b/src/Zip.Shared/ZipEntry.Write.cs index b11d03c..dadb68a 100644 --- a/src/Zip.Shared/ZipEntry.Write.cs +++ b/src/Zip.Shared/ZipEntry.Write.cs @@ -192,9 +192,59 @@ internal void WriteCentralDirectoryEntry(Stream s) (this._container.ZipFile.MaxOutputSegmentSize64 != 0); if (segmented) // workitem 13915 { - // Emit nonzero disknumber only if saving segmented archive. - bytes[i++] = (byte)(_diskNumber & 0x00FF); - bytes[i++] = (byte)((_diskNumber & 0xFF00) >> 8); + if (_presumeZip64 || _diskNumber > 0xFFFF) + { + /* + * From spec: + 4.5.3 -Zip64 Extended Information Extra Field (0x0001): + + The following is the layout of the zip64 extended + information "extra" block. If one of the size or + offset fields in the Local or Central directory + record is too small to hold the required data, + a Zip64 extended information record is created. + The order of the fields in the zip64 extended + information record is fixed, but the fields MUST + only appear if the corresponding Local or Central + directory record field is set to 0xFFFF or 0xFFFFFFFF. + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (ZIP64) 0x0001 2 bytes Tag for this "extra" block type + Size 2 bytes Size of this "extra" block + Original + Size 8 bytes Original uncompressed file size + Compressed + Size 8 bytes Size of compressed data + Relative Header + Offset 8 bytes Offset of local header record + Disk Start + Number 4 bytes Number of the disk on which + this file starts + + * + * As of 2019, major tools actually enforce this constraint and + * would display warnings (7-Zip) or even not unzip archives (WinZip) + * that have a header set in Zip64, but doesn't have -1 value in + * appropriate fields of the record itself. + * + * Currently we always set 'Relative Header' and 'Disk Start' inside + * the Extra block for Zip64, meaning that we also need to make sure + * that their non-Zip64 counterparts would be -1 (0xFFFFFFFF + * and 0xFFFF respectively), regardless of the fact if the value fits + * into uint32/uint16 range or not. + */ + bytes[i++] = 0xFF; + bytes[i++] = 0xFF; + } + else + { + // Emit nonzero disknumber only if saving segmented archive. + bytes[i++] = (byte)(_diskNumber & 0x00FF); + bytes[i++] = (byte)((_diskNumber & 0xFF00) >> 8); + } } else { @@ -220,14 +270,19 @@ internal void WriteCentralDirectoryEntry(Stream s) // workitem 11131 // relative offset of local header. // - // If necessary to go to 64-bit value, then emit 0xFFFFFFFF, - // else write out the value. - // - // Even if zip64 is required for other reasons - number of the entry - // > 65534, or uncompressed size of the entry > MAX_INT32, the ROLH - // need not be stored in a 64-bit field . - if (_RelativeOffsetOfLocalHeader > 0xFFFFFFFFL) // _OutputUsesZip64.Value - { + // If necessary to go to 64-bit value or when Zip64 is required, then + // emit 0xFFFFFFFF, else write out the value. + if (_presumeZip64 || _RelativeOffsetOfLocalHeader > 0xFFFFFFFFL) + { + /* + * See spec & more details above in _diskNumber section + * + * Currently we always set 'Relative Header' and 'Disk Start' inside + * the Extra block for Zip64, meaning that we also need to make sure + * that their non-Zip64 counterparts would be -1 (0xFFFFFFFF + * and 0xFFFF respectively), regardless of the fact if the value fits + * into uint32/uint16 range or not. + */ bytes[i++] = 0xFF; bytes[i++] = 0xFF; bytes[i++] = 0xFF; @@ -369,8 +424,9 @@ private byte[] ConstructExtraField(bool forCentralDirectory) i += 8; // starting disk number - Array.Copy(BitConverter.GetBytes(0), 0, block, i, 4); + Array.Copy(BitConverter.GetBytes(_diskNumber), 0, block, i, 4); } + listOfBlocks.Add(block); } From 18e5e77116b9e2346b63de8a892cec673e45a6bd Mon Sep 17 00:00:00 2001 From: darkms Date: Wed, 23 Oct 2019 20:59:10 +0700 Subject: [PATCH 10/11] Bumped version --- .semver | 2 +- src/SolutionInfo.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.semver b/.semver index 03a7b4c..3435259 100644 --- a/.semver +++ b/.semver @@ -1,6 +1,6 @@ --- :major: 1 :minor: 13 -:patch: 4 +:patch: 5 :special: '' :metadata: '' diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index 61286cc..b6ee969 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -1,6 +1,6 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -[assembly: AssemblyVersion("1.13.4")] -[assembly: AssemblyFileVersion("1.13.4")] -[assembly: AssemblyInformationalVersion("1.13.4.000000")] +[assembly: AssemblyVersion("1.13.5")] +[assembly: AssemblyFileVersion("1.13.5")] +[assembly: AssemblyInformationalVersion("1.13.5.000000")] From a9cc4bd5984dd97f5954723f3f3524bce9acde3d Mon Sep 17 00:00:00 2001 From: darkms Date: Wed, 23 Oct 2019 21:44:11 +0700 Subject: [PATCH 11/11] Added more tests for other Zip64 Options to make sure other modes don't break --- src/Zip Tests/SplitArchives.cs | 129 ++++++++++++++++++++++++--------- 1 file changed, 94 insertions(+), 35 deletions(-) diff --git a/src/Zip Tests/SplitArchives.cs b/src/Zip Tests/SplitArchives.cs index f2db8fc..9dbc3cd 100644 --- a/src/Zip Tests/SplitArchives.cs +++ b/src/Zip Tests/SplitArchives.cs @@ -722,9 +722,26 @@ public void Spanned_WinZip_Unzip_wi13691() } } + public void WinZip_Unzip(string zipFilePath, string extractDir) + { + var args = string.Format("-d -yx {0} \"{1}\"", + zipFilePath, extractDir); + Exec(wzunzip, args); + } + + public void SevenZip_Unzip(string zipFilePath, string extractDir) + { + var args = string.Format("x {0} -o\"{1}\"", + zipFilePath, extractDir); + var output = Exec(sevenZip, args); + Assert.IsTrue( + output.IndexOf("error", StringComparison.OrdinalIgnoreCase) == -1, + "Output contains errors: " + output); + } + [TestMethod] [Timeout(15 * 60 * 1000)] - public void Spanned_Zip64_HugeFiles_WinZip_Unzip() + public void Spanned_Zip64Always_HugeFiles_WinZip_Unzip() { if (!WinZipIsPresent) throw new Exception("winzip is not present"); @@ -734,17 +751,13 @@ public void Spanned_Zip64_HugeFiles_WinZip_Unzip() 6 * 1024 * 1024 * 1024L, // 5GB span (over default non-Zip64 '4GB' limit) 5 * 1024 * 1024 * 1024L, - (zipFilePath, extractDir) => - { - var args = string.Format("-d -yx {0} \"{1}\"", - zipFilePath, extractDir); - Exec(wzunzip, args); - }); + Zip64Option.Always, + WinZip_Unzip); } [TestMethod] [Timeout(15 * 60 * 1000)] - public void Spanned_Zip64_SmallFiles_WinZip_Unzip() + public void Spanned_Zip64Always_SmallFiles_WinZip_Unzip() { if (!WinZipIsPresent) throw new Exception("winzip is not present"); @@ -754,17 +767,45 @@ public void Spanned_Zip64_SmallFiles_WinZip_Unzip() 2 * 1024 * 1024L, // 1MB span 1 * 1024 * 1024L, - (zipFilePath, extractDir) => - { - var args = string.Format("-d -yx {0} \"{1}\"", - zipFilePath, extractDir); - Exec(wzunzip, args); - }); + Zip64Option.Always, + WinZip_Unzip); + } + + [TestMethod] + [Timeout(15 * 60 * 1000)] + public void Spanned_Zip64AsNecessary_SmallFiles_WinZip_Unzip() + { + if (!WinZipIsPresent) + throw new Exception("winzip is not present"); + + Test_SpannedZip64_Unzip_Compatibility( + // 2MB files + 2 * 1024 * 1024L, + // 1MB span + 1 * 1024 * 1024L, + Zip64Option.AsNecessary, + WinZip_Unzip); + } + + [TestMethod] + [Timeout(15 * 60 * 1000)] + public void Spanned_Zip64Never_SmallFiles_WinZip_Unzip() + { + if (!WinZipIsPresent) + throw new Exception("winzip is not present"); + + Test_SpannedZip64_Unzip_Compatibility( + // 2MB files + 2 * 1024 * 1024L, + // 1MB span + 1 * 1024 * 1024L, + Zip64Option.Never, + WinZip_Unzip); } [TestMethod] [Timeout(15 * 60 * 1000)] - public void Spanned_Zip64_HugeFiles_7Zip_Unzip() + public void Spanned_Zip64Always_HugeFiles_7Zip_Unzip() { if (!SevenZipIsPresent) throw new Exception("7-zip is not present"); @@ -774,20 +815,13 @@ public void Spanned_Zip64_HugeFiles_7Zip_Unzip() 6 * 1024 * 1024 * 1024L, // 5GB span (over default non-Zip64 '4GB' limit) 5 * 1024 * 1024 * 1024L, - (zipFilePath, extractDir) => - { - var args = string.Format("x {0} -o\"{1}\"", - zipFilePath, extractDir); - var output = Exec(sevenZip, args); - Assert.IsTrue( - output.IndexOf("error", StringComparison.OrdinalIgnoreCase) == -1, - "Output contains errors: " + output); - }); + Zip64Option.Always, + SevenZip_Unzip); } [TestMethod] [Timeout(15 * 60 * 1000)] - public void Spanned_Zip64_SmallFiles_7Zip_Unzip() + public void Spanned_Zip64Always_SmallFiles_7Zip_Unzip() { if (!SevenZipIsPresent) throw new Exception("7-zip is not present"); @@ -797,17 +831,41 @@ public void Spanned_Zip64_SmallFiles_7Zip_Unzip() 2 * 1024 * 1024L, // 1MB span 1 * 1024 * 1024L, - (zipFilePath, extractDir) => - { - var args = string.Format("x {0} -o\"{1}\"", - zipFilePath, extractDir); - var output = Exec(sevenZip, args); - Assert.IsTrue( - output.IndexOf("error", StringComparison.OrdinalIgnoreCase) == -1, - "Output contains errors: " + output); - }); + Zip64Option.Always, + SevenZip_Unzip); } + [TestMethod] + [Timeout(15 * 60 * 1000)] + public void Spanned_Zip64AsNecessary_SmallFiles_7Zip_Unzip() + { + if (!SevenZipIsPresent) + throw new Exception("7-zip is not present"); + + Test_SpannedZip64_Unzip_Compatibility( + // 2MB files + 2 * 1024 * 1024L, + // 1MB span + 1 * 1024 * 1024L, + Zip64Option.AsNecessary, + SevenZip_Unzip); + } + + [TestMethod] + [Timeout(15 * 60 * 1000)] + public void Spanned_Zip64Never_SmallFiles_7Zip_Unzip() + { + if (!SevenZipIsPresent) + throw new Exception("7-zip is not present"); + + Test_SpannedZip64_Unzip_Compatibility( + // 2MB files + 2 * 1024 * 1024L, + // 1MB span + 1 * 1024 * 1024L, + Zip64Option.Never, + SevenZip_Unzip); + } #if INFOZIP_UNZIP_SUPPORTS_SPLIT_ARCHIVES @@ -972,6 +1030,7 @@ public void Spanned_InfoZip_Zip_wi13691() private void Test_SpannedZip64_Unzip_Compatibility( long fileSize, long spanSize, + Zip64Option zip64Option, Action unzipAction) { TestContext.WriteLine("Creating fodder files... {0}", @@ -995,7 +1054,7 @@ private void Test_SpannedZip64_Unzip_Compatibility( using (var zipFile = new ZipFile()) { - zipFile.UseZip64WhenSaving = Zip64Option.Always; + zipFile.UseZip64WhenSaving = zip64Option; // disable compression to make sure out 0-filled files would keep their size zipFile.CompressionLevel = Zlib.CompressionLevel.None; zipFile.MaxOutputSegmentSize64 = spanSize;