Skip to content

Decompress result went wrong after push over 128K #19

@EfveZombie

Description

@EfveZombie

I use fstd as one of my WebStream style adapter, my code is simple:

		const transform = new TransformStream<Uint8Array, Uint8Array>();
		this.readable = transform.readable;
		const writer = transform.writable.getWriter();
		const decompressor = new Decompress((chunk, isLast) => {
			writer.write(chunk);
			if (isLast) {
				writer.close();
			}
		});
		this.writable = new WritableStream<Uint8Array>({
			write: (chunk) => {
				decompressor.push(chunk);
			},
		});

I ported the test cases from Go, and it didn't pass the large cases:

		/*****************************************************************
		 * 5. fixtures/*.zst parity (if such folder exists in the project)
		 *****************************************************************/
		describe("sample files in ./fixtures (optional)", () => {
			let dirEntries: string[] = [];
			try {
				dirEntries = readdirSync(join(__dirname, "fixtures"));
			} catch {
				// directory absent – that’s fine, keep suite silent
				return;
			}

			dirEntries
				.filter((f) => f.endsWith(".zst"))
				.forEach((file) => {
					it(file, async () => {
						const compressed = readFileSync(join(__dirname, "fixtures", file));
						const dec = newDecompressor(type);

						const out = await pipeOnce(dec, compressed);

						// Expected SHA-256 prefix is encoded in the file-name, just like the Go test.
						const want = file.split(".")[0];
						const got = createHash("sha256").update(out).digest("hex").slice(0, 8);
						expect(got).toBe(want);
					});
				});
		});

		/*****************************************************************
		 * 6. parity with the system “zstd” binary (if present)
		 *****************************************************************/
		describe("compatibility with the reference CLI (optional)", () => {
			let zstdPath: string | null = null;

			try {
				zstdPath = execFileSync("which", ["zstd"]).toString().trim();
			} catch {
				/* zstd not installed – skip the sub-suite */
			}

			if (!zstdPath) return;

			it("can decode the CLI output", async () => {
				// const big = new TextEncoder().encode("hello world ".repeat(400_000));
				const big = new TextEncoder().encode("hello world ".repeat(11_000));
				const compressed = execFileSync(zstdPath, { input: big });

				const dec = newDecompressor(type);
				await expectPipe(dec, compressed, big);
			});
		});

Especially the final case, it worked well when repeat times < 10_000, then went wrong after > 11_000. I think there may be some bug near 2^17 bytes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions