python / python/cpython

`zipfile`: file type issues

未关闭
#133,324 4 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

stdlib type-bug
主要语言
Python
星标
77.2k
派生
35.9k
PR 合并指标
PR 指标待抓取

描述

Bug report

Bug description:

Hey.

I think there exist a number of issues (which may, depending on how code is used, in principle even be security relevant).

First, AFAIU, ZIP files may contain (at least) regular files, directories (as "standalone" items in the archive, like an empty directory) and symbolic links.

For example using the zip program:

$ mkdir empty
$ zip d.zip empty
  adding: empty/ (stored 0%)
$ ln -s /dev/null bar
$ zip --symlinks  s.zip bar 
  adding: bar (stored 0%)
$

When I open the one with the symlink in Python:

>>> import zipfile

>>> z = zipfile.ZipFile("s.zip", "r")
>>> z.namelist()
['bar']

>>> f = z.open("bar", "r")
>>> f.read()
b'/dev/null'

>>> i = z.getinfo("bar")
>>> i.is_dir()
False

>>> p = zipfile.Path(z, "bar")

>>> p.filename
PosixPath('s.zip/bar')

>>> p.is_dir()
False

>>> p.is_file()
True

>>> p.is_symlink()
True

>>>
  1. It's IMO debatable whether z.open("<symlink>", "r") should succeed or not. IMO zipfile.ZipFile.open() quite clearly is ZIP's open(), but that AFAIK, never opens symlinks but only follows them.
  2. Even if that behaviour is desired (i.e. like a os.readlink() for ZIPs), then it's still completely unexpected and the ZipFile object has no is_symlink()-method ... (only zipfile.Path has such, so one needs to create that first, which seems quite unhandy).
  3. Speaking of which zipfile.Path’s is_dir(), is_file() and is_symlink() functions seem either buggy or semantically inconsistent and/or badly documented.
    Usually, "file" means either any type of file (directory, symlink, device, etc.) or regular files (and sometimes also symlinks if they point to regular files).
    Here, the symlink points to nothing, so it cannot be the latter case. Also - see below - a directory wouldn't return True for is_file(), so the it's not the former either.
    The docs also don't meantion what "file" means.

Now the same with d.zip:

>>> import zipfile
>>> z = zipfile.ZipFile("d.zip", "r")
>>> z.namelist()
['empty/']

>>> f = z.open("empty/", "r")
>>> f.read()
b''

>>> i = archive_file.getinfo("empty/")
>>> i.is_dir()
True

>>> p = zipfile.Path(z,"empty/")
>>> p.filename
PosixPath('d.zip/empty')

>>> p.is_dir()
True

>>> p.is_file()
False

>>> p.is_symlink()
False

>>>
  1. IMO, that zipfile.ZipFile.open() succeeds on a directory (and gives an empty bytes) seems pretty strange at best. It does so even if the directory isn't empty but contains files.
  2. There's also that thing that sometimes that directory pathnames are suffixed by / and sometimes not. Maybe I've missed it but that doesn't seem to be documented, but may be crucial when e.g. matching filenames - and is IMO unexpected.
  3. As mentioned above, is_file() here is False, which would imply that the meaning of that function should be that a file is either a regular file or a regular file or a symbolic link pointing to such.

Cheers,
Chris.

CPython versions tested on:

3.13

Operating systems tested on:

Linux

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

首先,使用 zipfile.ZipFile.open()、ZipInfo.is_dir() 以及 zipfile.Path.is_dir()、is_file() 和 is_symlink() 重现 Python 3.13 示例。阅读相关的 zipfile 文档和测试,然后在定义完成标准之前,确定目录、普通文件、符号链接和末尾斜杠的预期语义。

由索引模型根据 Issue 内容生成。

评估

技术栈
python
领域
operating-systems
Issue 类型
缺陷
难度
5/5
预计耗时
一周以上
活跃度
停滞
描述清晰度
需要澄清
新手友好度
25/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。