101arrowz / fflate

High performance (de)compression in an 8kB package

Home Page:https://101arrowz.github.io/fflate

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`gunzipSync` failing (0 gzip length) on some npm package tarballs

andrewbranch opened this issue · comments

I’ve found three npm packages that fail to gunzip with fflate (the resulting length is 0), but work with Node.js’s zlib. Here’s a full repro:

// index.mjs
import { gunzipSync as zlibGunzipSync } from "zlib";
import { gunzipSync } from "fflate";

const brokenPackages = [
  "https://registry.npmjs.org/openurl/-/openurl-1.0.2.tgz",
  "https://registry.npmjs.org/is/-/is-0.0.7.tgz",
  "https://registry.npmjs.org/youtube/-/youtube-0.0.5.tgz",
];

for (const url of brokenPackages) {
  const tarballData = new Uint8Array(
    await fetch(url).then((r) => r.arrayBuffer())
  );

  console.log("fflate", gunzipSync(tarballData).length);
  console.log("zlib", zlibGunzipSync(tarballData).length);
}

That would be because those particular package tarballs have a bunch of zero padding at the end (for some reason?), and fflate expects a footer to be in the right position. I don't think that's actually spec compliant - GZIP supports concatenated streams (i.e. it would be OK to have a second GZIP header right after the first one and another full stream) but I don't think it's supposed to have padding. In any case you should be able to resolve this with the streaming API, which doesn't look at any footers and supports concatenated GZIP streams (if any of those are on NPM too).

const chunks = [];
new fflate.Gunzip(chunk => chunks.push(chunk)).push(tarballData, true);
console.log("fflate streaming", Buffer.concat(chunks).length);