pypa / build

A simple, correct Python build frontend

Home Page:https://build.pypa.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Building with Python 3.11.4 generates tarfile.LinkOutsideDestinationError

effigies opened this issue · comments

I have a project where the changelog lives in the root of the repository and I link to it from the doc directory so that it's part of our docs:

project/
  doc/
    source/
      changelog.rst -> ../../Changelog
      ...
    ...
  project/
    ...
  Changelog
  ...

As of Python 3.11.4, attempting to run python -m build produces:

❯ python -m build                                            
* Creating venv isolated environment...
* Installing packages in isolated environment... (hatch-vcs, hatchling)
* Getting build dependencies for sdist...
* Building sdist...

Traceback (most recent call last):
  File "/home/chris/mambaforge/envs/py3114/lib/python3.11/site-packages/build/__main__.py", line 388, in main
    built = build_call(
            ^^^^^^^^^^^
  File "/home/chris/mambaforge/envs/py3114/lib/python3.11/site-packages/build/__main__.py", line 247, in build_package_via_sdist
    t.extractall(sdist_out)
  File "/home/chris/mambaforge/envs/py3114/lib/python3.11/tarfile.py", line 2249, in extractall
    tarinfo = self._get_extract_tarinfo(member, filter_function, path)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/chris/mambaforge/envs/py3114/lib/python3.11/tarfile.py", line 2303, in _get_extract_tarinfo
    self._handle_fatal_error(e)
  File "/home/chris/mambaforge/envs/py3114/lib/python3.11/tarfile.py", line 2301, in _get_extract_tarinfo
    tarinfo = filter_function(tarinfo, path)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/chris/mambaforge/envs/py3114/lib/python3.11/tarfile.py", line 819, in data_filter
    new_attrs = _get_filtered_attrs(member, dest_path, True)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/chris/mambaforge/envs/py3114/lib/python3.11/tarfile.py", line 806, in _get_filtered_attrs
    raise LinkOutsideDestinationError(member, target_path)
tarfile.LinkOutsideDestinationError: 'nibabel-5.2.0.dev36+g30ba615e/doc/source/changelog.rst' would link to '/Changelog', which is outside the destination

ERROR 'nibabel-5.2.0.dev36+g30ba615e/doc/source/changelog.rst' would link to '/Changelog', which is outside the destination

If I run either python -m build -s or python -m build -w, this error does not occur.

What version of CPython are using (including the patch value)? I think this is a bug that was fixed only in the latest patch release (fix in CPytjon landed something like two weeks ago). I think we are going to have to figure out how to work around the bug for the broken patch releases.

$ python
Python 3.11.4 | packaged by conda-forge | (main, Jun 10 2023, 18:08:17) [GCC 12.2.0] on linux

Oops, you mentioned it. Yep, 3.11.5 is the one with python/cpython#107845.

Got it. I assumed that, because this just started showing up in CI, that this was the latest Python. I can see if I can avoid 3.11.4.

It started showing up because we started using the data filter if it is present in build 1.0.0. I don’t remember exactly when it was added 3.11.3? Of course it’s a different patch number for every minor release of Python. 🤦

python -m build -s -w

will also work (it doesn’t unpack the SDist, the bug only gets hit if you unpack a tarball).

I think we are going to have to figure out how to work around the bug for the broken patch releases.

Just catching the error and saying that extraction is broken for packages with symlinks at the root for 3.11.4 but fixed in 3.11.5 would be good enough for me. I spent a bit trying to figure out if I did have broken links before I realized this was an upstream bug, so just clearly communicating the known failure condition would work.

You are in a rather special situation being able to control your Python patch version. Most users can't do that very easily. We can just avoid using the buggy data filter on versions of Python that contain the bug. (Also 3.8-3.10 still haven't had a release that fixes this bug).

Glad to see that the patch is not too painful.