Skip to content

[codex] Avoid retaining caller input after non-blocking gzwrite stall - #1302

Open
maxvanamersfort wants to merge 1 commit into
madler:developfrom
maxvanamersfort:fix-gzwrite-nonblocking-stall
Open

[codex] Avoid retaining caller input after non-blocking gzwrite stall#1302
maxvanamersfort wants to merge 1 commit into
madler:developfrom
maxvanamersfort:fix-gzwrite-nonblocking-stall

Conversation

@maxvanamersfort

Copy link
Copy Markdown

Summary

  • avoid retaining caller-owned input after a non-blocking gzwrite() stall
  • save a bounded accepted prefix in zlib's internal input buffer
  • include the saved bytes in the return value and stream position

Fixes #1292.

Root cause

The large-write path points strm.next_in directly at the caller's buffer.
If writing compressed output stalls with EAGAIN, gz_comp() returns while
next_in and avail_in still describe the unconsumed caller input. A later
small gzwrite() or gzputc() assumes that pending input belongs to
state->in, performs pointer arithmetic across unrelated allocations, and
can write out of bounds.

Leaving the caller pointer pending for a later retry is also not sufficient:
the caller may release that buffer after the partial return, and retrying the
reported remainder would duplicate data once zlib consumed the retained input.

On a non-blocking stall, this change accepts at most one internal buffer of the
remaining input, copies that prefix into zlib-owned storage, and reports those
bytes as accepted. The caller retains responsibility for the rest.

Impact

This restores the internal-buffer invariant before the public write call
returns, preventing the out-of-bounds write and the related stale-pointer
read while preserving partial-write semantics for compressed and transparent
output.

Validation

  • deterministic Linux ASan/UBSan reproduction before the fix: SEGV in
    memcpy() from gz_write() at gzwrite.c:217
  • the same trigger completes without a sanitizer finding after the fix
  • differential non-blocking round trip verifies that accepted input appears
    exactly once, without loss or duplication
  • strict C89 compilation with -Wall -Wextra -Werror
  • ./configure && make -j2 test (static, shared, and 64-bit tests)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Heap write past caller's buffer in gz_write()/gzputc() after non-blocking write stall

1 participant