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

Reply via email to