Skip to content

zipfile.ZipFile.repack() returns wrong data to already-open readers #154842

Description

@fedonman

Bug description:

ZipFile.repack() moves member data to lower offsets, but a ZipExtFile from an earlier
open() keeps its own absolute position, so it silently returns data from the wrong place:

import io, zipfile
data = bytes((i * 7) & 0xFF for i in range(300_000))
buf = io.BytesIO()
with zipfile.ZipFile(buf, 'w') as zf:
    zf.writestr('a.txt', b'A' * 100_000)
    zf.writestr('c.txt', data)
with zipfile.ZipFile(buf, 'a') as zf:
    fh = zf.open('c.txt')
    fh.read(100)
    zf.repack([zf.remove('a.txt')])
    print('correct data:', fh.read(200_000) == data[100:200_100])
    fh.read()
correct data: False
zipfile.BadZipFile: Bad CRC-32 for file 'c.txt'

repack() guards only self._writing, so an open reading handle is not rejected.
_fileRefCnt already counts them: it is incremented only in the read path.

repack() is new in 3.16, so no released version is affected.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions