File bh42369-thread-safety-zipfile-SharedFile.patch of Package python3.34506

From 9ec41b7252cee917c269a228998b8c465bb9466c Mon Sep 17 00:00:00 2001
From: Kevin Mehall <km@kevinmehall.net>
Date: Tue, 29 Jun 2021 17:13:04 -0700
Subject: [PATCH] Fix thread safety of zipfile._SharedFile.tell

The `_SharedFile` tracks its own virtual position into the file as
`self._pos` and updates it after reading or seeking. `tell()` should
return this position instead of calling into the underlying file object,
since if multiple `_SharedFile` instances are being used concurrently on
the same file, another one may have moved the real file position.
Additionally, calling into the underlying `tell` may expose thread
safety issues in the underlying file object because it was called
without taking the lock.

Prior to this fix, the test case in
https://bugs.python.org/issue42369#msg381212
reliably caused a `zipfile.BadZipFile: Bad CRC-32 for file 'file1'`
after a few dozen reads; with this fix I have not seen this error.

From-PR: gh#python/cpython!26974
Fixes: gh#python/cpython#86535
Patch: bh42369-thread-safety-zipfile-SharedFile.patch
---
 Lib/zipfile.py                                     | 14 ++++++++++++++
 .../2022-03-19-19-56-04.bpo-42369.Ok828t.rst       |  1 +
 2 files changed, 15 insertions(+)
 create mode 100644 Misc/NEWS.d/next/Library/2022-03-19-19-56-04.bpo-42369.Ok828t.rst

diff --git a/Lib/zipfile.py b/Lib/zipfile.py
index 8e5550aacf5..0e497b60a0f 100644
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -718,6 +718,20 @@ class _SharedFile:
         self._close = close
         self._lock = lock
         self._writing = writing
+        self.seekable = file.seekable
+
+    def tell(self):
+        return self._pos
+
+    def seek(self, offset, whence=0):
+        with self._lock:
+            if self._writing():
+                raise ValueError("Can't reposition in the ZIP file while "
+                        "there is an open writing handle on it. "
+                        "Close the writing handle before trying to read.")
+            self._file.seek(offset, whence)
+            self._pos = self._file.tell()
+            return self._pos
 
     def read(self, n=-1):
         with self._lock:
diff --git a/Misc/NEWS.d/next/Library/2022-03-19-19-56-04.bpo-42369.Ok828t.rst b/Misc/NEWS.d/next/Library/2022-03-19-19-56-04.bpo-42369.Ok828t.rst
new file mode 100644
index 00000000000..86dc3a0b81b
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-03-19-19-56-04.bpo-42369.Ok828t.rst
@@ -0,0 +1 @@
+Fix thread safety of :meth:`zipfile._SharedFile.tell` to avoid a "zipfile.BadZipFile: Bad CRC-32 for file" exception when reading a :class:`ZipFile` from multiple threads.
-- 
2.45.0
openSUSE Build Service is sponsored by