Skip to content

Commit

Permalink
Merge pull request #508 from 5saviahv/update
Browse files Browse the repository at this point in the history
Descriptor check & Main Header locating
  • Loading branch information
5saviahv committed Jun 23, 2024
2 parents ba4e198 + c5222b4 commit f8d11ae
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 7 deletions.
11 changes: 11 additions & 0 deletions headers/entryHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ module.exports = function () {
}
},

get flags_desc() {
return (_flags & Constants.FLG_DESC) > 0;
},
set flags_desc(val) {
if (val) {
_flags |= Constants.FLG_DESC;
} else {
_flags &= ~Constants.FLG_DESC;
}
},

get method() {
return _method;
},
Expand Down
Binary file added test/assets/stream-nozip64.zip
Binary file not shown.
8 changes: 8 additions & 0 deletions test/methods/methods.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ describe("adm-zip.js - methods handling local files", () => {
].sort()
);
});

it("zip.extractAllTo(destination) - streamed file", () => {
const zip = new Zip("./test/assets/stream-nozip64.zip");
zip.extractAllTo(destination);
const files = walk(destination);

expect(files.sort()).to.deep.equal([pth.normalize("./test/xxx/lorem.txt")]);
});
});

describe(".extractAllToAsync - sync", () => {
Expand Down
41 changes: 36 additions & 5 deletions zipEntry.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,46 @@ module.exports = function (/** object */ options, /*Buffer*/ input) {
}

function crc32OK(data) {
// if bit 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the header is written
if ((_centralHeader.flags & 0x8) !== 0x8) {
// if bit 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the local header is written
if (!_centralHeader.flags_desc) {
if (Utils.crc32(data) !== _centralHeader.localHeader.crc) {
return false;
}
} else {
// @TODO: load and check data descriptor header
// The fields in the local header are filled with zero, and the CRC-32 and size are appended in a 12-byte structure
// (optionally preceded by a 4-byte signature) immediately after the compressed data:
const descriptor = {};
const dataEndOffset = _centralHeader.realDataOffset + _centralHeader.compressedSize;
// no descriptor after compressed data, instead new local header
if (input.readUInt32LE(dataEndOffset) == Constants.LOCSIG || input.readUInt32LE(dataEndOffset) == Constants.CENSIG) {
throw new Error("ADM-ZIP: No descriptor present");
}

// get decriptor data
if (input.readUInt32LE(dataEndOffset) == Constants.EXTSIG) {
// descriptor with signature
descriptor.crc = input.readUInt32LE(dataEndOffset + Constants.EXTCRC);
descriptor.compressedSize = input.readUInt32LE(dataEndOffset + Constants.EXTSIZ);
descriptor.size = input.readUInt32LE(dataEndOffset + Constants.EXTLEN);
} else if (input.readUInt16LE(dataEndOffset + 12) === 0x4b50) {
// descriptor without signature (we check is new header starting where we expect)
descriptor.crc = input.readUInt32LE(dataEndOffset + Constants.EXTCRC - 4);
descriptor.compressedSize = input.readUInt32LE(dataEndOffset + Constants.EXTSIZ - 4);
descriptor.size = input.readUInt32LE(dataEndOffset + Constants.EXTLEN - 4);
} else {
throw new Error("ADM-ZIP: Unknown descriptor format");
}

// check data integrity
if (descriptor.compressedSize !== _centralHeader.compressedSize || descriptor.size !== _centralHeader.size || descriptor.crc !== _centralHeader.crc) {
throw new Error("ADM-ZIP: Descriptor data is malformed");
}
if (Utils.crc32(data) !== descriptor.crc) {
return false;
}

// @TODO: zip64 bit descriptor fields
// if bit 3 is set and any value in local header "zip64 Extended information" extra field are set 0 (place holder)
// then 64-bit descriptor format is used instead of 32-bit
// central header - "zip64 Extended information" extra field should store real values and not place holders
}
return true;
}
Expand Down
8 changes: 6 additions & 2 deletions zipFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
endOffset = -1, // Start offset of the END header
commentEnd = 0;

// option to search header form entire file
const trailingSpace = typeof opts.trailingSpace === "boolean" ? opts.trailingSpace : false;
if (trailingSpace) max = 0;

for (i; i >= n; i--) {
if (inBuffer[i] !== 0x50) continue; // quick check that the byte is 'P'
if (inBuffer.readUInt32LE(i) === Utils.Constants.ENDSIG) {
Expand All @@ -102,7 +106,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
}
}

if (!~endOffset) throw new Error(Utils.Errors.INVALID_FORMAT);
if (endOffset == -1) throw new Error(Utils.Errors.INVALID_FORMAT);

mainHeader.loadFromBinary(inBuffer.slice(endOffset, endStart));
if (mainHeader.commentLength) {
Expand Down Expand Up @@ -225,7 +229,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
const len = name.length;

entryList.forEach(function (zipEntry) {
if (zipEntry.entryName.substr(0, len) === name) {
if (zipEntry.entryName.startsWith(name)) {
list.push(zipEntry);
}
});
Expand Down

0 comments on commit f8d11ae

Please sign in to comment.