Skip to content

Commit

Permalink
pythongh-102956: Fix returning of empty byte strings after seek in zi…
Browse files Browse the repository at this point in the history
…pfile module

Taken from python#103565
  • Loading branch information
Jokimax authored and mgorny committed Oct 24, 2023
1 parent 4365c91 commit da3b427
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 5 deletions.
16 changes: 16 additions & 0 deletions Lib/test/test_zipfile/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2235,6 +2235,22 @@ def test_seek_tell(self):
fp.seek(0, os.SEEK_SET)
self.assertEqual(fp.tell(), 0)

def test_read_after_seek(self):
# Issue 102956: Make sure seek(x, os.SEEK_CUR) doesn't break read()
txt = b"Charge men!"
bloc = txt.find(b"men")
with zipfile.ZipFile(TESTFN, "w") as zipf:
zipf.writestr("foo.txt", txt)
with zipfile.ZipFile(TESTFN, mode="r") as zipf:
with zipf.open("foo.txt", "r") as fp:
fp.seek(bloc, os.SEEK_CUR)
self.assertEqual(fp.read(-1), b'men!')
with zipfile.ZipFile(TESTFN, mode="r") as zipf:
with zipf.open("foo.txt", "r") as fp:
fp.read(6)
fp.seek(1, os.SEEK_CUR)
self.assertEqual(fp.read(-1), b'men!')

@requires_bz2()
def test_decompress_without_3rd_party_library(self):
data = b'PK\x05\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Expand Down
10 changes: 5 additions & 5 deletions Lib/zipfile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1121,8 +1121,12 @@ def seek(self, offset, whence=os.SEEK_SET):
read_offset = new_pos - curr_pos
buff_offset = read_offset + self._offset

if buff_offset >= 0 and buff_offset < len(self._readbuffer):
# Just move the _offset index if the new position is in the _readbuffer
self._offset = buff_offset
read_offset = 0
# Fast seek uncompressed unencrypted file
if self._compress_type == ZIP_STORED and self._decrypter is None and read_offset > 0:
elif self._compress_type == ZIP_STORED and self._decrypter is None and read_offset > 0:
# disable CRC checking after first seeking - it would be invalid
self._expected_crc = None
# seek actual file taking already buffered data into account
Expand All @@ -1133,10 +1137,6 @@ def seek(self, offset, whence=os.SEEK_SET):
# flush read buffer
self._readbuffer = b''
self._offset = 0
elif buff_offset >= 0 and buff_offset < len(self._readbuffer):
# Just move the _offset index if the new position is in the _readbuffer
self._offset = buff_offset
read_offset = 0
elif read_offset < 0:
# Position is before the current position. Reset the ZipExtFile
self._fileobj.seek(self._orig_compress_start)
Expand Down

0 comments on commit da3b427

Please sign in to comment.