Gzip 1.15 Fixes a Row of Bugs Marked 'Present Since the Beginning', Including a Buffer Overflow

Gzip 1.15 Fixes a Row of Bugs Marked 'Present Since the Beginning', Including a Buffer Overflow

Gzip 1.15 shipped on September 20, the first release since 1.14 in April 2025, with more than a hundred commits behind it.

The changelog is unusual for how many entries end with the same bracketed note: [bug present since the beginning].

The ones that matter

Deleting the wrong file. Gzip could remove the wrong file if another process simultaneously renamed an ancestor directory of gzip’s destination. That is a time-of-check to time-of-use race: gzip resolves a path, something moves a directory underneath it, and the unlink lands somewhere other than where gzip decided it should. Narrow to hit and unpleasant when it does.

A buffer overflow. Decompressing an .lzh file after decompressing a .Z file could overflow a buffer. Note the precondition: not one file, but one file after another in the same process. State left behind by the first decompression sets up the overflow in the second.

Use of uninitialized memory on some malformed inputs.

Two more .lzh corruption bugs, both from state carried over rather than reset. An internal bit buffer that was not cleared, and a decoding table from the previous file being applied to the next.

Rejecting valid zip files. gzip -d refused PKZIP signatures, local headers and data descriptors, all of which appear in well-formed streamed zip files.

Plus quoting of unusual characters in diagnostics, an --synchronous fix dating to 1.7 rather than to the beginning, and a temporary file race in gzexe, zdiff and znew on platforms lacking mktemp.

The pattern worth naming

Four of those are memory-safety or state-reuse bugs in decompression code that has been in essentially every Linux system since the early 1990s.

Decompressors are a hostile-input parser by definition. You hand them a file, they interpret it as a structured format, and a malformed file is the attacker’s input. The .lzh path is worse than most because it is legacy support almost nobody exercises, which means it gets the least fuzzing and the fewest eyes.

That lands with some force in the same month that Mold is moving to Rust, Ubuntu finished replacing GNU coreutils with the Rust implementation, and Google is deleting its C Binder driver in favour of the Rust one. The memory-safety argument is not abstract. It is a thirty-year-old buffer overflow in a tool on every machine you own.

The counterpoint is equally fair: these bugs were found and fixed, by maintainers who kept working on a tool most people assume is finished, and the fix arrived without anyone needing to rewrite anything.

Also in 1.15

Locale handling changed. Gzip previously assumed the C locale and now follows the environment, which affects filename quoting and diagnostics. If you parse gzip’s output in scripts, that is the change most likely to surprise you.

# force predictable output in scripts
LC_ALL=C gzip -d somefile.gz

Platforms dropped: FreeBSD 4.11, HP-UX 11.00, Minix 3.1.8, and Windows 8.1 via MinGW without UCRT.

Should you update

Take it when your distribution ships it. Nothing here is remotely exploitable in normal use, and the overflow and uninitialized-memory fixes are worth having on anything that decompresses files it did not create.

If you handle untrusted archives at any volume, that is a stronger yes, and the general advice in our backup comparison applies: the compression format is a dependency, and dependencies that parse attacker-controlled input deserve to be current.

gzip --version | head -1

Background reading

Explainers for the concepts behind this story.