diff --git a/src/pip/_internal/utils/unpacking.py b/src/pip/_internal/utils/unpacking.py index c9e7a9a06fc..0d85d1fee72 100644 --- a/src/pip/_internal/utils/unpacking.py +++ b/src/pip/_internal/utils/unpacking.py @@ -5,6 +5,7 @@ import os import shutil import stat +import sys import tarfile import zipfile from typing import Callable, Iterable, List, Optional @@ -201,7 +202,23 @@ def pip_filter(member: tarfile.TarInfo, path: str) -> tarfile.TarInfo: member.name = split_leading_dir(member.name)[1] orig_mode = member.mode try: - member = data_filter(member, location) + try: + member = data_filter(member, location) + except tarfile.LinkOutsideDestinationError: + if sys.version_info[:3] in { + (3, 8, 17), + (3, 9, 17), + (3, 10, 12), + (3, 11, 4), + }: + # The tarfile filter in specific Python versions + # raises LinkOutsideDestinationError on valid input + # (https://github.com/python/cpython/issues/107845) + # Ignore the error there, but do use the + # more lax `tar_filter` + member = tarfile.tar_filter(member, location) + else: + raise except tarfile.TarError as exc: message = "Invalid member in the tar file {}: {}" # Filter error messages mention the member name. @@ -226,6 +243,7 @@ def pip_filter(member: tarfile.TarInfo, path: str) -> tarfile.TarInfo: finally: tar.close() + def _untar_without_filter( filename: str, location: str,