Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
ChangeLog file for zlib

Changes in 1.3.2.1 (xx Feb 2026)
-
- Fix gz_write() crash and corruption after a stall on a non-blocking
destination: input left pending in the caller's buffer by a partial
direct write was assumed to be in the internal input buffer, causing
an out-of-bounds copy on the next write, and could be compressed a
second time when the caller resubmitted it

Changes in 1.3.2 (17 Feb 2026)
- Continued rewrite of CMake build [Vollstrecker]
Expand Down
16 changes: 16 additions & 0 deletions gzwrite.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,22 @@ local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
if (state->skip && gz_zero(state) == -1)
return 0;

/* If input is still pending from a previous write that stalled on a
non-blocking destination, and that pending input is not in the input
buffer, then it is in the caller's buffer, left there by a direct
(large) write. Such input was not counted as consumed when the
previous partial result was returned, so the caller will provide it
again, starting at the current position of the new call's buffer.
Since that pending input has not yet been given to deflate, nothing
is lost by dropping the pending reference to it here and letting
this call's input be compressed in its place. (Input pending in
the input buffer itself must be kept, as it was already counted as
consumed and is not being provided again.) */
if (state->strm.avail_in &&
(state->strm.next_in < state->in ||
state->strm.next_in >= state->in + state->size))
state->strm.avail_in = 0;

/* for small len, copy to input buffer, otherwise compress directly */
if (len < state->size) {
/* copy to input buffer, compress when full */
Expand Down