From 4ffedb750f3d5b51e1934b65a8e5a858353913c9 Mon Sep 17 00:00:00 2001 From: Thomas Benndorf Date: Thu, 4 Jul 2024 15:01:13 +0700 Subject: [PATCH 1/3] fixed zip64 entry condition --- lib/Open/directory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Open/directory.js b/lib/Open/directory.js index 20b9e5f..b45059e 100644 --- a/lib/Open/directory.js +++ b/lib/Open/directory.js @@ -121,7 +121,7 @@ module.exports = function centralDirectory(source, options) { // https://github.com/golang/go/blob/master/src/archive/zip/reader.go#L503 // For zip64 files, need to find zip64 central directory locator header to extract // relative offset for zip64 central directory record. - if (vars.numberOfRecords == 0xffff|| vars.numberOfRecords == 0xffff || + if (vars.diskNumber == 0xffff || vars.numberOfRecords == 0xffff || vars.offsetToStartOfCentralDirectory == 0xffffffff) { // Offset to zip64 CDL is 20 bytes before normal CDR From a8b057f5d649baf0e0a8ac1c32d28bedcd8b6c16 Mon Sep 17 00:00:00 2001 From: Thomas Benndorf Date: Thu, 4 Jul 2024 15:34:58 +0700 Subject: [PATCH 2/3] fixes #324 - parsing of ZIP64 extra entry --- lib/parseExtraField.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/parseExtraField.js b/lib/parseExtraField.js index 42d178f..683709c 100644 --- a/lib/parseExtraField.js +++ b/lib/parseExtraField.js @@ -6,19 +6,22 @@ module.exports = function(extraField, vars) { while(!extra && extraField && extraField.length) { const candidateExtra = parseBuffer.parse(extraField, [ ['signature', 2], - ['partsize', 2], - ['uncompressedSize', 8], - ['compressedSize', 8], - ['offset', 8], - ['disknum', 8], + ['partSize', 2], ]); if(candidateExtra.signature === 0x0001) { - extra = candidateExtra; + // parse buffer based on data in ZIP64 central directory; order is important! + const fieldsToExpect = []; + if (vars.uncompressedSize === 0xffffffff) fieldsToExpect.push(['uncompressedSize', 8]); + if (vars.compressedSize === 0xffffffff) fieldsToExpect.push(['compressedSize', 8]); + if (vars.offsetToLocalFileHeader === 0xffffffff) fieldsToExpect.push(['offsetToLocalFileHeader', 8]); + + // slice off the 4 bytes for signature and partSize + extra = parseBuffer.parse(extraField.slice(4), fieldsToExpect); } else { // Advance the buffer to the next part. // The total size of this part is the 4 byte header + partsize. - extraField = extraField.slice(candidateExtra.partsize + 4); + extraField = extraField.slice(candidateExtra.partSize + 4); } } @@ -31,7 +34,7 @@ module.exports = function(extraField, vars) { vars.uncompressedSize= extra.uncompressedSize; if (vars.offsetToLocalFileHeader === 0xffffffff) - vars.offsetToLocalFileHeader= extra.offset; + vars.offsetToLocalFileHeader = extra.offsetToLocalFileHeader; return extra; }; From 99650390f1521d25ee1e29d1cdb75bd0fb58ed6a Mon Sep 17 00:00:00 2001 From: Thomas Benndorf Date: Mon, 8 Jul 2024 11:54:21 +0700 Subject: [PATCH 3/3] added some test cases for parsing zip64 extra fields --- test/zip64.js | 73 +++++++++++++++++++++- testData/zip64-allextrafields.zip | Bin 0 -> 250 bytes testData/zip64-extrafieldoffsetlength.zip | Bin 0 -> 234 bytes 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 testData/zip64-allextrafields.zip create mode 100644 testData/zip64-extrafieldoffsetlength.zip diff --git a/test/zip64.js b/test/zip64.js index bd34ca0..64fbb63 100644 --- a/test/zip64.js +++ b/test/zip64.js @@ -9,6 +9,7 @@ const temp = require('temp'); const UNCOMPRESSED_SIZE = 5368709120; const ZIP64_OFFSET = 72; const ZIP64_SIZE = 36; +const ZIP64_EXTRA_FIELD_OFFSET = 0; t.test('Correct uncompressed size for zip64', function (t) { const archive = path.join(__dirname, '../testData/big.zip'); @@ -43,7 +44,77 @@ t.test('Correct uncompressed size for zip64', function (t) { t.end(); }); -t.test('Parse files from zip64 format correctly', function (t) { +t.test('Parse files with all zip64 extra fields correctly', function (t) { + const archive = path.join(__dirname, '../testData/zip64-allextrafields.zip'); + + t.test('in unzipper.Open', function(t) { + unzip.Open.file(archive) + .then(function(d) { + d.files[0].stream() + .on('vars', function(vars) { + t.same(vars.extra.uncompressedSize, ZIP64_SIZE, 'Open: Extra field'); + t.same(vars.extra.compressedSize, ZIP64_SIZE, 'Open: Extra field'); + t.same(vars.extra.offsetToLocalFileHeader, ZIP64_EXTRA_FIELD_OFFSET, 'Open: Extra field'); + t.same(vars.uncompressedSize, ZIP64_SIZE, 'Open: File header'); + t.same(vars.compressedSize, ZIP64_SIZE, 'Open: File header'); + t.same(vars.offsetToLocalFileHeader, ZIP64_EXTRA_FIELD_OFFSET, 'Open: File header'); + t.end(); + }) + .on('error', function(e) { + t.same(e.message, 'FILE_ENDED'); + t.end(); + }); + }); + }); + + t.test('in unzipper.extract', function (t) { + temp.mkdir('node-unzip-', function (err, dirPath) { + if (err) { + throw err; + } + fs.createReadStream(archive) + .pipe(unzip.Extract({ path: dirPath })) + .on('close', function() { t.end(); }); + }); + }); + + t.end(); +}); + +t.test('Parse files with zip64 extra field with only offset length correctly', function (t) { + const archive = path.join(__dirname, '../testData/zip64-extrafieldoffsetlength.zip'); + + t.test('in unzipper.Open', function(t) { + unzip.Open.file(archive) + .then(function(d) { + d.files[0].stream() + .on('vars', function(vars) { + t.same(vars.extra.offsetToLocalFileHeader, ZIP64_EXTRA_FIELD_OFFSET, 'Open: Extra field'); + t.same(vars.offsetToLocalFileHeader, ZIP64_EXTRA_FIELD_OFFSET, 'Open: File header'); + t.end(); + }) + .on('error', function(e) { + t.same(e.message, 'FILE_ENDED'); + t.end(); + }); + }); + }); + + t.test('in unzipper.extract', function (t) { + temp.mkdir('node-unzip-', function (err, dirPath) { + if (err) { + throw err; + } + fs.createReadStream(archive) + .pipe(unzip.Extract({ path: dirPath })) + .on('close', function() { t.end(); }); + }); + }); + + t.end(); +}); + +t.test('Parse files from regular zip64 format correctly', function (t) { const archive = path.join(__dirname, '../testData/zip64.zip'); t.test('in unzipper.Open', function(t) { diff --git a/testData/zip64-allextrafields.zip b/testData/zip64-allextrafields.zip new file mode 100644 index 0000000000000000000000000000000000000000..34f6884ba9e25acd4accdc746c4402ede3c75c49 GIT binary patch literal 250 zcmWIWW@Zs#U|`^2Feu@2tb6`HQw7KaVKyKRa&>g^b>%*JLMKe)obQ>FfgY#Nc!n~3 zGWsmC$cFihkI1D@-9^IQUv@AAcr!BTGV7w4^dAb?7-WFr5U`{XBnUB=kwF4%6G#SR xBQgl^W@FQV3g|L`%!L3(G&%sv_khwsee59S3@9I@KERt5g^b>%*JLMKe)obQ>FfgY#Nc!n~3 zGWsmC$cFihkI1D@-9^IQUv@AAcr!BTGV9_ni3cbS0ZSVH0|CTbMxd=Q5a7+mrUT{Z nGJwp107f+00m}D)(m;LeAZ7=Y4^kiC%?ffn1IQ*AU|;|Mk0dg& literal 0 HcmV?d00001