Skip to content

gzseek()/gztell() read uninitialized state->past in write mode, silently corrupting output (since a4e4521) #1303

Description

@jxravi

Summary

gz_reset() initializes state->past only inside the state->mode == GZ_READ
branch, but since commit
a4e4521
gzseek64() and gztell64() read it in either mode. gz_open() allocates
gz_state with a plain malloc() and does not zero it, so a write-mode handle reads
past out of indeterminate heap.

Two consequences, both write-mode only:

  1. Silent output corruption. Two SEEK_CUR seeks with no write between them can
    drop the accumulated zero-fill, producing a well-formed gzip stream with a valid
    CRC and the wrong contents.
  2. gztell() returns the wrong position after a deferred seek, breaking the
    documented gztell(file) == gzseek(file, 0L, SEEK_CUR) equivalence in zlib.h.

Affected: v1.3.1.2, v1.3.2, master, develop — all reproduced below.
v1.3.1 and earlier are unaffected. Still present on develop.

Root cause

gzlib.c, gz_reset():

local void gz_reset(gz_statep state) {
    state->x.have = 0;              /* no output data available */
    if (state->mode == GZ_READ) {   /* for reading ... */
        state->eof = 0;             /* not at end of file */
        state->past = 0;            /* <-- only initialized for reading */
        state->how = LOOK;
        state->junk = -1;
    }
    else                            /* for writing ... */
        state->reset = 0;
    state->again = 0;
    state->skip = 0;                /* no seek request pending */
    ...
}

The two write-mode readers, both added by a4e4521:

/* gzseek64() */
else {
    offset += state->past ? 0 : state->skip;
    state->skip = 0;
}

/* gztell64() */
return state->x.pos + (state->past ? 0 : state->skip);

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions