Skip to content

gh-154490: Only keep permission bits of the mode argument in ZipFile.mkdir()#154509

Open
DevoidSloth wants to merge 1 commit into
python:mainfrom
DevoidSloth:gh-154490-zipfile-mkdir-mode
Open

gh-154490: Only keep permission bits of the mode argument in ZipFile.mkdir()#154509
DevoidSloth wants to merge 1 commit into
python:mainfrom
DevoidSloth:gh-154490-zipfile-mkdir-mode

Conversation

@DevoidSloth

@DevoidSloth DevoidSloth commented Jul 22, 2026

Copy link
Copy Markdown

ZipFile.mkdir() combines the caller-provided mode into the entry's external attributes without clearing the file type bits, so those bits can mark the created entry as something other than a directory:

>>> import io, stat, zipfile
>>> with zipfile.ZipFile(io.BytesIO(), 'w') as zh:
...     zh.mkdir('foo/', 0o107777)
...     print(oct(stat.S_IFMT(zh.getinfo('foo/').external_attr >> 16)))
...
0o140000   # socket, not a directory

This PR sanitizes mode to its permission bits before combining it with S_IFDIR, matching what stat.S_IMODE() does, as suggested in the issue:

zinfo.external_attr = (0o40000 | (mode & 0o7777)) << 16

It also spells the default mode as 0o777 instead of 511 in the signature and documentation, for consistency with os.mkdir() (same value, clearer intent).

Included:

  • Regression assertions in test_mkdir covering S_IFREG and S_IFLNK type bits in mode, plus an extractall() round-trip.
  • Documentation update for ZipFile.mkdir() with a versionchanged note.
  • NEWS entry.

…pFile.mkdir()

The file type bits of a caller-provided mode were previously mixed into
the entry's external attributes, so a mode such as 0o107777 could mark
the created entry as a socket instead of a directory.  Sanitize the mode
with & 0o7777, matching what stat.S_IMODE does, before combining it with
S_IFDIR.  Also spell the default mode as 0o777 instead of 511 in the
signature and documentation, for consistency with os.mkdir().
@python-cla-bot

python-cla-bot Bot commented Jul 22, 2026

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

@read-the-docs-community

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #33715264 | 📁 Comparing ed08556 against main (a2a8466)

  🔍 Preview build  

2 files changed
± library/zipfile.html
± whatsnew/changelog.html

@danny0838

danny0838 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

LGTM. But I would personally treat this as a bug fix and documentation improvement rather than a behavior change, which means that the detailed doc about behavior change across major versions is not needed and we can backport this to older maintaining Python versions.

The compatibility issue it may introduce should be minimal since there should be no actual requirement to call ZipFile.mkdir with file format bits other than a directory.

Tracing the history, the issue gh-84353 and related PR had a more significant behavior change and actually introduced a regression, while it was still implemented as a bug fix and has been backported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants