Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9ec41b7

Browse files
kevinmehallmcepl
authored andcommitted
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#86535 Patch: bh42369-thread-safety-zipfile-SharedFile.patch
1 parent d7133c7 commit 9ec41b7

File tree

2 files changed

+15
-0
lines changed

2 files changed

+15
-0
lines changed

Lib/zipfile.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,20 @@ def __init__(self, file, pos, close, lock, writing):
718718
self._close = close
719719
self._lock = lock
720720
self._writing = writing
721+
self.seekable = file.seekable
722+
723+
def tell(self):
724+
return self._pos
725+
726+
def seek(self, offset, whence=0):
727+
with self._lock:
728+
if self._writing():
729+
raise ValueError("Can't reposition in the ZIP file while "
730+
"there is an open writing handle on it. "
731+
"Close the writing handle before trying to read.")
732+
self._file.seek(offset, whence)
733+
self._pos = self._file.tell()
734+
return self._pos
721735

722736
def read(self, n=-1):
723737
with self._lock:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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.

0 commit comments

Comments
 (0)