]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-102956: Fix returning of empty byte strings after seek in zipfile … (GH...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 25 Oct 2023 00:32:08 +0000 (02:32 +0200)
committerGitHub <noreply@github.com>
Wed, 25 Oct 2023 00:32:08 +0000 (17:32 -0700)
gh-102956: Fix returning of empty byte strings after seek in zipfile … (GH-103565)
(cherry picked from commit c73b0f35602abf5f283bf64266641f19bc82fce0)

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>
Lib/test/test_zipfile/test_core.py
Lib/zipfile/__init__.py
Misc/NEWS.d/next/Library/2023-04-15-14-45-21.gh-issue-102956.Z6qeUy.rst [new file with mode: 0644]

index c2cc2c827ca69543226eb19a1d952f5cf75f49bf..d8a83d4dbba4d0f87b76e00c37c3e9189ba0a880 100644 (file)
@@ -2246,6 +2246,22 @@ class OtherTests(unittest.TestCase):
                 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'
index 5b981d5742c12ec10f48084f8f0370bea80e7ec8..59d105580a46bbc28f3cd5cdb74efbab225d04de 100644 (file)
@@ -1122,8 +1122,12 @@ class ZipExtFile(io.BufferedIOBase):
         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
@@ -1134,10 +1138,6 @@ class ZipExtFile(io.BufferedIOBase):
             # 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)
diff --git a/Misc/NEWS.d/next/Library/2023-04-15-14-45-21.gh-issue-102956.Z6qeUy.rst b/Misc/NEWS.d/next/Library/2023-04-15-14-45-21.gh-issue-102956.Z6qeUy.rst
new file mode 100644 (file)
index 0000000..1a4bb9b
--- /dev/null
@@ -0,0 +1 @@
+Fix returning of empty byte strings after seek in zipfile module