Repository navigation
zipfile: file type issues #133324
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on May 3, 2025 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.FWIW, I've made a PR to
zipp(upstream ofzipfile.Path) that fixes this: jaraco/zipp#132I assume you've changed it so that the trailing
/is removed?
Just a note in that case, the docs for ZipInfo.is_dir() and possibly other locations explicitly mention that directories should always end in a/(though no idea why).- addedstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
on May 4, 2025 directories should always end in a
/(though no idea why).The presence of a trailing slash is used by the ZIP file format to indicate a directory. There are other ways to record this (POSIX attributes, DOS flags) but a trailing slash is the most basic and widely-supported.
So I think the
ZipInfo.is_dir()behaviour is correct, becauseZipInforepresents the zip file member header in all its gory detail. Butzipfile.Pathshould hide this detail IMHO.Hmm. IMO this is kind of a problem in ZIP, that the same thing (e.g. marking something as a dir) might be done in different ways.
Another example would be the times/dates which may, AFAIU, be in the ZIP's central directory or in various extra fields (and all these may have different values).
A Python coder most likely wants to know e.g. is it a dir, is it a regular file, is it a symlink, which currently seems a bit non-straightforward.
Especially I think a programmer would rather want to have anis_dir()that catches all cases than having to look at various place (like "is there a trailing/).
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsNo status
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
zipprogram:When I open the one with the symlink in Python:
z.open("<symlink>", "r")should succeed or not. IMOzipfile.ZipFile.open()quite clearly is ZIP'sopen(), but that AFAIK, never opens symlinks but only follows them.os.readlink()for ZIPs), then it's still completely unexpected and the ZipFile object has nois_symlink()-method ... (onlyzipfile.Pathhas such, so one needs to create that first, which seems quite unhandy).zipfile.Path’sis_dir(),is_file()andis_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
Trueforis_file(), so the it's not the former either.The docs also don't meantion what "file" means.
Now the same with
d.zip:zipfile.ZipFile.open()succeeds on a directory (and gives an emptybytes) seems pretty strange at best. It does so even if the directory isn't empty but contains files./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.is_file()here isFalse, 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