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
Bug description:
ZipFile.repack()moves member data to lower offsets, but aZipExtFilefrom an earlieropen()keeps its own absolute position, so it silently returns data from the wrong place:repack()guards onlyself._writing, so an open reading handle is not rejected._fileRefCntalready 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