mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
[3.12] gh-102956: Fix returning of empty byte strings after seek in zipfile … (GH-103565) (#111289)
gh-102956: Fix returning of empty byte strings after seek in zipfile … (GH-103565)
(cherry picked from commit c73b0f3560
)
gh-102956: Fix returning of empty byte strings after seek in zipfile module. This was a regression in 3.12.0 due to a performance enhancement.
Co-authored-by: Jokimax <77680901+Jokimax@users.noreply.github.com>
This commit is contained in:
parent
a4eb2e308d
commit
6f130f231b
3 changed files with 22 additions and 5 deletions
|
@ -2246,6 +2246,22 @@ class OtherTests(unittest.TestCase):
|
||||||
fp.seek(0, os.SEEK_SET)
|
fp.seek(0, os.SEEK_SET)
|
||||||
self.assertEqual(fp.tell(), 0)
|
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()
|
@requires_bz2()
|
||||||
def test_decompress_without_3rd_party_library(self):
|
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'
|
data = b'PK\x05\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
|
|
@ -1122,8 +1122,12 @@ class ZipExtFile(io.BufferedIOBase):
|
||||||
read_offset = new_pos - curr_pos
|
read_offset = new_pos - curr_pos
|
||||||
buff_offset = read_offset + self._offset
|
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
|
# 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
|
# disable CRC checking after first seeking - it would be invalid
|
||||||
self._expected_crc = None
|
self._expected_crc = None
|
||||||
# seek actual file taking already buffered data into account
|
# seek actual file taking already buffered data into account
|
||||||
|
@ -1134,10 +1138,6 @@ class ZipExtFile(io.BufferedIOBase):
|
||||||
# flush read buffer
|
# flush read buffer
|
||||||
self._readbuffer = b''
|
self._readbuffer = b''
|
||||||
self._offset = 0
|
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:
|
elif read_offset < 0:
|
||||||
# Position is before the current position. Reset the ZipExtFile
|
# Position is before the current position. Reset the ZipExtFile
|
||||||
self._fileobj.seek(self._orig_compress_start)
|
self._fileobj.seek(self._orig_compress_start)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix returning of empty byte strings after seek in zipfile module
|
Loading…
Add table
Add a link
Reference in a new issue