adm-zip
Version:
Javascript implementation of zip for nodejs with support for electron original-fs. Allows user to create or extract zip files both in memory or to/from disk
65 lines (61 loc) • 2.73 kB
JavaScript
const version = +(process?.versions?.node ?? "").split(".")[0] || 0;
const Errors = require("../util/errors");
module.exports = function (/*Buffer*/ inbuf, /*number*/ expectedLength) {
var zlib = require("zlib");
// Cap decompression output at the entry's declared uncompressed size to bound
// decompression bombs (CVE-2026-39244). A declared size of 0 must not disable
// the cap: a genuinely empty entry inflates to 0 bytes, so a 1-byte floor
// still lets it through while stopping a bomb that lies about its size
// (GHSA-rcw4-f5rp-g42v). zlib requires maxOutputLength >= 1.
const maxOutputLength = expectedLength > 0 ? expectedLength : 1;
const option = version >= 15 ? { maxOutputLength } : {};
return {
inflate: function () {
return zlib.inflateRawSync(inbuf, option);
},
inflateAsync: function (/*Function*/ callback) {
var tmp = zlib.createInflateRaw(option),
parts = [],
total = 0,
done = false;
const fail = function (err) {
if (done) return;
done = true;
tmp.destroy();
callback && callback(Buffer.alloc(0), err);
};
// Route stream errors (e.g. Z_DATA_ERROR on malformed input) through the
// callback. Without an "error" listener zlib re-throws the event as an
// uncaught exception on a later tick, crashing the host process instead
// of failing the call (GHSA-8238-w5pm-2374).
tmp.on("error", function (err) {
fail(err);
});
tmp.on("data", function (data) {
if (done) return;
total += data.length;
// The streaming API ignores maxOutputLength, so enforce the cap by
// hand; otherwise the async path decompresses without limit while the
// sync path is capped (GHSA-v429-h5qx-84wm, GHSA-c6fg-446q-cg94).
if (total > maxOutputLength) {
return fail(Errors.MAX_OUTPUT_EXCEEDED());
}
parts.push(data);
});
tmp.on("end", function () {
if (done) return;
done = true;
var buf = Buffer.alloc(total),
written = 0;
buf.fill(0);
for (var i = 0; i < parts.length; i++) {
var part = parts[i];
part.copy(buf, written);
written += part.length;
}
callback && callback(buf);
});
tmp.end(inbuf);
}
};
};