From 17b673907950bc328d5216420d1f312977199b02 Mon Sep 17 00:00:00 2001 From: Filippo Tedeschi Date: Mon, 21 Sep 2026 11:33:14 +0200 Subject: [PATCH] Reset next_in and avoid undefined behavior in gzwrite. --- gzwrite.c | 10 +++++++--- test/example.c | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/gzwrite.c b/gzwrite.c index 3052259ea5..f1da3d0480 100644 --- a/gzwrite.c +++ b/gzwrite.c @@ -248,6 +248,7 @@ local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) { return state->again ? put - len : 0; } } while (len); + state->strm.next_in = state->in; } /* input was all buffered or compressed */ @@ -386,8 +387,11 @@ local int gz_vacate(gz_statep state) { z_streamp strm; strm = &(state->strm); - if (strm->next_in == NULL || - strm->next_in + strm->avail_in <= state->in + state->size) + if (strm->next_in == NULL || strm->avail_in == 0) { + strm->next_in = state->in; + return 0; + } + if (strm->next_in + strm->avail_in <= state->in + state->size) return 0; (void)gz_comp(state, Z_NO_FLUSH); if (strm->avail_in == 0) { @@ -454,7 +458,7 @@ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { } if (strm->avail_in == 0) strm->next_in = state->in; - next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in); + next = (char *)(strm->next_in + strm->avail_in); next[state->size - 1] = 0; #ifdef NO_vsnprintf # ifdef HAS_vsprintf_void diff --git a/test/example.c b/test/example.c index 9cc5f763bc..54d45f4d57 100644 --- a/test/example.c +++ b/test/example.c @@ -161,6 +161,26 @@ static void test_gzio(const char *fname, Byte *uncompr, uLong uncomprLen) { } gzclose(file); + + /* Test large buffer gzwrite followed immediately by gzprintf */ + file = gzopen(fname, "wb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + { + char large_buf[16384]; + memset(large_buf, 'A', sizeof(large_buf)); + if (gzwrite(file, large_buf, (unsigned)sizeof(large_buf)) != (int)sizeof(large_buf)) { + fprintf(stderr, "gzwrite err: %s\n", gzerror(file, &err)); + exit(1); + } + } + if (gzprintf(file, "%s", "test") != 4) { + fprintf(stderr, "gzprintf after large gzwrite err: %s\n", gzerror(file, &err)); + exit(1); + } + gzclose(file); #endif }