diff --git a/packages/dev/base/lib/api/services/helpers/files/gzip.test.ts b/packages/dev/base/lib/api/services/helpers/files/gzip.test.ts index c495dcbc..1507eda5 100644 --- a/packages/dev/base/lib/api/services/helpers/files/gzip.test.ts +++ b/packages/dev/base/lib/api/services/helpers/files/gzip.test.ts @@ -56,6 +56,14 @@ describe("gzip", () => { expect(() => gunzipped(new Uint8Array([...endless, ...new Uint8Array(8).fill(1)]))).toThrow("never ends"); }); + it("should refuse an extra field that claims more bytes than the data holds", () => { + // Arrange + const overlong = withHeader(4, [0xff, 0xff]); + + // Act & Assert + expect(() => gunzipped(overlong)).toThrow("The gzip header runs past the end of the data"); + }); + it("should refuse a trailer that claims more than the data can inflate to, without setting that much aside first", () => { // Arrange const lying = new Uint8Array(gzipSync(new TextEncoder().encode("abc"))); diff --git a/packages/dev/base/lib/api/services/helpers/files/gzip.ts b/packages/dev/base/lib/api/services/helpers/files/gzip.ts index 5ed0dd05..877aec25 100644 --- a/packages/dev/base/lib/api/services/helpers/files/gzip.ts +++ b/packages/dev/base/lib/api/services/helpers/files/gzip.ts @@ -59,9 +59,6 @@ export function gunzipped(bytes: Uint8Array, limit: number = MOST_INFLATED_BYTES } const size = uint32(bytes, end + UINT32_BYTES); const data = inflateRaw(bytes.subarray(start, end), size, limit); - if (data.length !== size) { - throw new Error(`The gzip data holds ${data.length} bytes, not the ${size} its trailer records`); - } if (crc32(data) !== uint32(bytes, end)) { throw new Error("The gzip data fails its CRC-32 check"); } diff --git a/packages/dev/base/lib/api/services/helpers/files/zip.test.ts b/packages/dev/base/lib/api/services/helpers/files/zip.test.ts index de4aed7c..300506d2 100644 --- a/packages/dev/base/lib/api/services/helpers/files/zip.test.ts +++ b/packages/dev/base/lib/api/services/helpers/files/zip.test.ts @@ -271,6 +271,15 @@ describe("zipStoredParts limits", () => { expect(() => zipStoredParts(tooBig)).toThrow("4 GB"); expect(() => zipStoredParts(tooMany)).toThrow("entries"); }); + + it("should refuse a name longer than the 16-bit length field a header gives it", () => { + // Arrange + const records = [{ name: "a.bin", size: 0, crc32: 0, data: "" }, { name: "a".repeat(0x10000), size: 0, crc32: 0, data: "" }]; + + // Act & Assert + expect(() => zipStoredParts(records)).toThrow("Zip entry 1 has a name longer than 65535 bytes"); + expect(zipEntries(zipStored([{ name: "a".repeat(0xffff), data: new Uint8Array(1) }]))[0]?.name).toHaveLength(0xffff); + }); }); describe("dosDateTime", () => {