Skip to content

gh-154667: Validate zipfile timestamps consistently - #154740

Open
Taeknology wants to merge 3 commits into
python:mainfrom
Taeknology:fix/gh-154667-zipfile-timestamp-validation
Open

Taeknology wants to merge 3 commits into
python:mainfrom
Taeknology:fix/gh-154667-zipfile-timestamp-validation

Conversation

@Taeknology

@Taeknology Taeknology commented Jul 26, 2026 •

Copy link
Copy Markdown
Contributor

Partially addresses #154667.

This PR is limited to ZipInfo.__init__() and ZipInfo.from_file():

  • Reject years after 2107 in the constructor with ValueError, matching the existing lower-bound validation.
  • When strict_timestamps=False, clamp filesystem timestamps whose converted year is outside 1980–2107, and clamp clearly out-of-range timestamps even when time.localtime() cannot convert them.
  • Preserve conversion errors for potentially representable timestamps. A platform limit, such as AIX's 2038 limit, does not mean the timestamp exceeds the ZIP range. The fallback conservatively preserves errors for UTC years 1979 through 2108, leaving room around the local-time ZIP boundaries. Conversion failures below that window clamp to 1980, including nonnegative timestamps from 1970–1978; they are not mistaken for upper-bound overflow.
  • Use 2107-12-31 23:59:58 as the upper clamp result so it survives ZIP's two-second encoding unchanged. This is the clamp result, not a new maximum for every input: an ordinary 2107-12-31 23:59:59 input remains accepted and is encoded as 58 seconds, as before.

This is not a shared sanitizer or a complete unification of timestamp handling. It does not change ZipInfo._for_archive(), post-construction date_time assignment, or normalize every strict-mode conversion exception to ValueError. PR #152452 separately addresses non-strict clamping in _for_archive() for SOURCE_DATE_EPOCH and the system clock.

Regression coverage includes simulated OverflowError and OSError at the AIX/32-bit limits and near both ZIP boundaries, strict-mode exception propagation, extreme timestamp clamping, and ZIP round-tripping.

Local validation

Using a debug build of this PR branch on Linux:

  • Existing ZipInfoTests: 9 passed before the follow-up change.
  • Regression tests failed before the corresponding fixes: 12 non-strict subtests for potentially valid timestamps and 6 subtests for nonnegative timestamps below the lower window. They pass after the fixes.
  • ./python -m unittest -v test.test_zipfile.test_core.ZipInfoTests: 10 passed, also checked under TZ=UTC0, TZ=EST5EDT, and TZ=JST-9.
  • ./python -m test test_zipfile test_shutil test_zipapp test_zipimport -j4: 991 run, 62 skipped, success.
  • ./python -m test test_zipfile -m '*ZipInfoTests*' -R 3:3: success; no reference leaks reported.

The AIX failure path is simulated; these tests were not run on AIX. These local results do not represent a new CI run or validation against the latest upstream main.

Signed-off-by: Taeknology <20297177+Taeknology@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

This PR is stale because it has been open for 90 days with no activity.

@github-actions github-actions Bot added the stale Stale PR or inactive for long period of time. label Oct 29, 2026
@Taeknology

Copy link
Copy Markdown
Contributor Author

@serhiy-storchaka, could you advise whether this focused scope is appropriate for a partial fix of #154667?

It covers constructor bounds and filesystem timestamp handling in from_file(), without introducing a shared sanitizer or changing _for_archive(). PR #152452 addresses a related _for_archive() clamping issue.

The follow-up preserves conversion errors for potentially valid ZIP timestamps rather than treating every localtime() failure as a ZIP-range overflow. Regression tests cover the simulated AIX 2038 limitation, timestamp boundaries, and extreme-value clamping.

A review of the scope and error-handling approach would be appreciated.

Include the upstream changes-builder fix for custom directives (pythongh-155100).

Validation on the merged tree:
- changes and HTML documentation builds passed.
- ZIP-related tests: 1,036 run, 62 skipped, success.
- ZipInfoTests reference-leak checks passed.
@github-actions github-actions Bot removed the stale Stale PR or inactive for long period of time. label Nov 6, 2026
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.

1 participant