diff --git a/docs/news.rst b/docs/news.rst index fb5b16b2..3d431050 100644 --- a/docs/news.rst +++ b/docs/news.rst @@ -10,6 +10,9 @@ Release Notes values) is now delegated to ``setuptools>=57.0.0`` (#466). The package dependencies were updated to reflect this change. - Fixed potential DoS attack via the ``WHEEL_INFO_RE`` regular expression +- Fixed ``ValueError: ZIP does not support timestamps before 1980`` when using + ``SOURCE_DATE_EPOCH=0`` or when on-disk timestamps are earlier than 1980-01-01. Such + timestamps are now changed to the minimum value before packaging. **0.37.1 (2021-12-22)** diff --git a/src/wheel/wheelfile.py b/src/wheel/wheelfile.py index b985774e..f55fc737 100644 --- a/src/wheel/wheelfile.py +++ b/src/wheel/wheelfile.py @@ -20,12 +20,14 @@ -(?P[^-]+?)-(?P[^-]+?)-(?P[^.]+?)\.whl$""", re.VERBOSE, ) +MINIMUM_TIMESTAMP = 315532800 # 1980-01-01 00:00:00 UTC def get_zipinfo_datetime(timestamp=None): # Some applications need reproducible .whl files, but they can't do this without # forcing the timestamp of the individual ZipInfo objects. See issue #143. timestamp = int(os.environ.get("SOURCE_DATE_EPOCH", timestamp or time.time())) + timestamp = max(timestamp, MINIMUM_TIMESTAMP) return time.gmtime(timestamp)[0:6] diff --git a/tests/test_bdist_wheel.py b/tests/test_bdist_wheel.py index 5ed9a41e..2a4d777a 100644 --- a/tests/test_bdist_wheel.py +++ b/tests/test_bdist_wheel.py @@ -202,3 +202,19 @@ def test_wheelfile_line_endings(wheel_paths): wheelfile = next(fn for fn in wf.filelist if fn.filename.endswith("WHEEL")) wheelfile_contents = wf.read(wheelfile) assert b"\r" not in wheelfile_contents + + +def test_unix_epoch_timestamps(dummy_dist, monkeypatch, tmpdir): + monkeypatch.setenv("SOURCE_DATE_EPOCH", "0") + monkeypatch.chdir(dummy_dist) + subprocess.check_call( + [ + sys.executable, + "setup.py", + "bdist_wheel", + "-b", + str(tmpdir), + "--universal", + "--build-number=2", + ] + )