python / python/cpython

zipfile should reject inconsistent disk information in EOCDR

Open
#155,639 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

stdlib type-bug
Dominant language
Python
Stars
77.2k
Forks
35.9k
PR merge metrics
PR metrics pending

Description

Bug report

Bug description:

zipfile is explicitly documented as not handling multipart (i.e. multi-disk) ZIPs.

However, zipfile also does not check the EOCDR's state for consistency with that invariant.

Two fields are relevant (offsets are relative to the start of the EOCDR):

  • "number of this disk" (offset 4, size 2)
  • "number of the disk with the start of the central directory" (offset 6, size 2)

In zipfile's model, both of these should always be 0, since there's exactly one "disk."

However, at the moment, zipfile appears to silently ignore these fields and allows a parse even when they're incoherent or inconsistent with each other. For example:

import io
import struct
import zipfile

archive = io.BytesIO()
with zipfile.ZipFile(archive, "w") as zipf:
    zipf.writestr("entry.txt", b"payload")
data = bytearray(archive.getvalue())
eocd = data.rfind(zipfile.stringEndArchive)
struct.pack_into("<H", data, eocd + 4, 1)
with zipfile.ZipFile(io.BytesIO(data)) as zipf:
    print(zipf.namelist())

This exposes ['entry.txt'], whereas other parsers (Rust's zip and async_zip, Info-ZIP, and 7-ZIP) reject the ZIP as malformed.

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

Linked PRs
  • gh-155814

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the issue's BytesIO example and tracing zipfile's EOCDR parsing, focusing on the two disk-number fields at offsets 4 and 6. Done means malformed archives with nonzero or inconsistent disk information are rejected rather than parsed successfully; the issue links PR gh-155814 for ongoing work.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.