New submission from Joe Jevnik: In zipfile.py only OSError is checked to see if seek fails:
``` def _EndRecData64(fpin, offset, endrec): """ Read the ZIP64 end-of-archive records and use that to update endrec """ try: fpin.seek(offset - sizeEndCentDir64Locator, 2) except OSError: # If the seek fails, the file is not large enough to contain a ZIP64 # end-of-archive record, so just return the end record we were given. return endrec ``` I belive that this should also catch ValueError so that other file-like objects may be passed to ZipFile. The particular case I ran into was passing an mmap object: ``` """ $ python p.py sys.version_info(major=3, minor=6, micro=0, releaselevel='final', serial=0) [] Traceback (most recent call last): File "p.py", line 34, in <module> with mmap_shared_raw_zipfile(f.name) as zf: File "/usr/lib64/python3.6/contextlib.py", line 82, in __enter__ return next(self.gen) File "p.py", line 23, in mmap_shared_raw_zipfile ZipFile(mm) as zf: File "/usr/lib64/python3.6/zipfile.py", line 1100, in __init__ self._RealGetContents() File "/usr/lib64/python3.6/zipfile.py", line 1163, in _RealGetContents endrec = _EndRecData(fp) File "/usr/lib64/python3.6/zipfile.py", line 264, in _EndRecData return _EndRecData64(fpin, -sizeEndCentDir, endrec) File "/usr/lib64/python3.6/zipfile.py", line 196, in _EndRecData64 fpin.seek(offset - sizeEndCentDir64Locator, 2) ValueError: seek out of range """ from contextlib import contextmanager import mmap import sys from tempfile import NamedTemporaryFile from zipfile import ZipFile print(sys.version_info) @contextmanager def mmap_shared_raw_zipfile(path): """Open a zipfile with mmap shared so the data can be shared in multiple processes. Parameters ---------- path : str The path the zipfile to open. Notes ----- The context manager returns a :class:`zipfile.ZipFile` on enter. """ with open(path) as f, \ mmap.mmap(f.fileno(), 0, mmap.MAP_SHARED, mmap.PROT_READ) as mm, \ ZipFile(mm) as zf: yield zf with NamedTemporaryFile() as f: ZipFile(f, mode='w').close() print(ZipFile(f.name).infolist()) with NamedTemporaryFile() as f: ZipFile(f, mode='w').close() with mmap_shared_raw_zipfile(f.name) as zf: print(zf.infolist()) ``` ---------- components: Library (Lib) messages: 287185 nosy: llllllllll priority: normal severity: normal status: open title: zipfile should catch ValueError as well as OSError to detect bad seek calls versions: Python 3.6 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue29468> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com