Skip to content

Bug report: Gzip operation produces invalid streams when using comments with header checksum #2243

@williballenthin

Description

@williballenthin

Describe the bug
When the Gzip operation is configured with both a comment and "Include file checksum" enabled, the resulting stream has a corrupted header CRC and cannot be decompressed.

src/core/operations/Gzip.mjs, run() method, lines 65-75

if (comment.length) {
    options.flags.comment = true;
    options.comment = comment;
}
const gzipObj = new Zlib.Gzip(new Uint8Array(input), options);
const compressed = new Uint8Array(gzipObj.compress());
if (options.flags.comment && !(compressed[3] & 0x10)) {
    compressed[3] |= 0x10;
}
return compressed.buffer;

The code manually sets the FCOMMENT flag bit (0x10) after zlibjs has already calculated and written the header CRC16. This post-hoc bit-flip corrupts the checksum.

To Reproduce
add Gzip with Comment = test and "Include file checksum" enabled, input hello hello hello, then attempt to decompress with Gunzip or gzip -d. Result: Error: invalid header crc16.

Screenshots

Image

Additional context
The zlibjs library expects the comment flag via options.flags.fcomment before calling .compress(), which lets it include the flag when calculating the header CRC. Fix:

if (comment.length) {
    options.flags.comment = true;
    options.flags.fcomment = true;
    options.comment = comment;
}
const gzipObj = new Zlib.Gzip(new Uint8Array(input), options);
const compressed = new Uint8Array(gzipObj.compress());
return compressed.buffer;

The manual bit manipulation should be removed entirely — zlibjs handles flag bits internally when configured correctly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions