From 6df22b83607763734d38f65c59d859a3ad474c5d Mon Sep 17 00:00:00 2001 From: Max van Amersfort Date: Tue, 25 Aug 2026 10:28:33 +0200 Subject: [PATCH] Avoid retaining caller input after gzwrite stall --- gzwrite.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/gzwrite.c b/gzwrite.c index b5026e5fad..ef04033887 100644 --- a/gzwrite.c +++ b/gzwrite.c @@ -183,7 +183,7 @@ local int gz_zero(gz_statep state) { /* Write len bytes from buf to file. Return the number of bytes written. If the returned value is less than len, then there was an error. If the error - was a non-blocking stall, then the number of bytes consumed is returned. + was a non-blocking stall, then the number of bytes accepted is returned. For any other error, 0 is returned. */ local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) { z_size_t put = len; @@ -242,8 +242,25 @@ local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) { n -= state->strm.avail_in; state->x.pos += n; len -= n; - if (ret == -1) - return state->again ? put - len : 0; + if (ret == -1) { + if (state->again) { + /* Save an accepted prefix of the remaining input. Never + leave next_in pointing into the caller's buffer after + returning. */ + unsigned save = state->strm.avail_in; + + if (save > state->size) + save = state->size; + if (save) + memcpy(state->in, state->strm.next_in, save); + state->strm.next_in = state->in; + state->strm.avail_in = save; + state->x.pos += save; + len -= save; + return put - len; + } + return 0; + } } while (len); }