Compare commits

..

No commits in common. "c8" and "c9s" have entirely different histories.
c8 ... c9s

36 changed files with 1762 additions and 1622 deletions

1
.fmf/version Normal file
View File

@ -0,0 +1 @@
1

8
.gitignore vendored
View File

@ -1 +1,7 @@
SOURCES/pip-9.0.3.tar.gz
/*.tar.gz
/*.zip
/pip-*/
/pip/
/results_python-pip/
*.rpm

View File

@ -1 +0,0 @@
1f5f44d433ca599d40f8e46f440479b2c73802d8 SOURCES/pip-9.0.3.tar.gz

111
9760.patch Normal file
View File

@ -0,0 +1,111 @@
From 960c01adce491de00ef7a8d02a32fea31b15a1dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
Date: Fri, 2 Apr 2021 02:39:11 +0200
Subject: [PATCH] Update urllib3 to 1.26.4 to fix CVE-2021-28363
---
news/CVE-2021-28363.vendor.rst | 1 +
src/pip/_vendor/urllib3/_version.py | 2 +-
src/pip/_vendor/urllib3/connection.py | 8 ++++++--
src/pip/_vendor/urllib3/exceptions.py | 12 +++++++++++-
src/pip/_vendor/urllib3/util/retry.py | 1 +
src/pip/_vendor/vendor.txt | 2 +-
6 files changed, 21 insertions(+), 5 deletions(-)
create mode 100644 news/CVE-2021-28363.vendor.rst
diff --git a/news/CVE-2021-28363.vendor.rst b/news/CVE-2021-28363.vendor.rst
new file mode 100644
index 00000000000..29700ab7469
--- /dev/null
+++ b/news/CVE-2021-28363.vendor.rst
@@ -0,0 +1 @@
+Update urllib3 to 1.26.4 to fix CVE-2021-28363
diff --git a/src/pip/_vendor/urllib3/_version.py b/src/pip/_vendor/urllib3/_version.py
index 2dba29e3fbe..97c983300b0 100644
--- a/src/pip/_vendor/urllib3/_version.py
+++ b/src/pip/_vendor/urllib3/_version.py
@@ -1,2 +1,2 @@
# This file is protected via CODEOWNERS
-__version__ = "1.26.2"
+__version__ = "1.26.4"
diff --git a/src/pip/_vendor/urllib3/connection.py b/src/pip/_vendor/urllib3/connection.py
index 660d679c361..45580b7e1ea 100644
--- a/src/pip/_vendor/urllib3/connection.py
+++ b/src/pip/_vendor/urllib3/connection.py
@@ -67,7 +67,7 @@ class BrokenPipeError(Exception):
# When it comes time to update this value as a part of regular maintenance
# (ie test_recent_date is failing) update it to ~6 months before the current date.
-RECENT_DATE = datetime.date(2019, 1, 1)
+RECENT_DATE = datetime.date(2020, 7, 1)
_CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]")
@@ -215,7 +215,7 @@ def putrequest(self, method, url, *args, **kwargs):
def putheader(self, header, *values):
""""""
- if SKIP_HEADER not in values:
+ if not any(isinstance(v, str) and v == SKIP_HEADER for v in values):
_HTTPConnection.putheader(self, header, *values)
elif six.ensure_str(header.lower()) not in SKIPPABLE_HEADERS:
raise ValueError(
@@ -490,6 +490,10 @@ def _connect_tls_proxy(self, hostname, conn):
self.ca_cert_dir,
self.ca_cert_data,
)
+ # By default urllib3's SSLContext disables `check_hostname` and uses
+ # a custom check. For proxies we're good with relying on the default
+ # verification.
+ ssl_context.check_hostname = True
# If no cert was provided, use only the default options for server
# certificate validation
diff --git a/src/pip/_vendor/urllib3/exceptions.py b/src/pip/_vendor/urllib3/exceptions.py
index d69958d5dfc..cba6f3f560f 100644
--- a/src/pip/_vendor/urllib3/exceptions.py
+++ b/src/pip/_vendor/urllib3/exceptions.py
@@ -289,7 +289,17 @@ class ProxySchemeUnknown(AssertionError, URLSchemeUnknown):
# TODO(t-8ch): Stop inheriting from AssertionError in v2.0.
def __init__(self, scheme):
- message = "Not supported proxy scheme %s" % scheme
+ # 'localhost' is here because our URL parser parses
+ # localhost:8080 -> scheme=localhost, remove if we fix this.
+ if scheme == "localhost":
+ scheme = None
+ if scheme is None:
+ message = "Proxy URL had no scheme, should start with http:// or https://"
+ else:
+ message = (
+ "Proxy URL had unsupported scheme %s, should use http:// or https://"
+ % scheme
+ )
super(ProxySchemeUnknown, self).__init__(message)
diff --git a/src/pip/_vendor/urllib3/util/retry.py b/src/pip/_vendor/urllib3/util/retry.py
index ee51f922f84..d25a41b42ea 100644
--- a/src/pip/_vendor/urllib3/util/retry.py
+++ b/src/pip/_vendor/urllib3/util/retry.py
@@ -253,6 +253,7 @@ def __init__(
"Using 'method_whitelist' with Retry is deprecated and "
"will be removed in v2.0. Use 'allowed_methods' instead",
DeprecationWarning,
+ stacklevel=2,
)
allowed_methods = method_whitelist
if allowed_methods is _Default:
diff --git a/src/pip/_vendor/vendor.txt b/src/pip/_vendor/vendor.txt
index 51a5508479e..868baba6f01 100644
--- a/src/pip/_vendor/vendor.txt
+++ b/src/pip/_vendor/vendor.txt
@@ -13,7 +13,7 @@ requests==2.25.1
certifi==2020.12.05
chardet==4.0.0
idna==2.10
- urllib3==1.26.2
+ urllib3==1.26.4
resolvelib==0.5.4
retrying==1.3.3
setuptools==44.0.0

View File

@ -1,90 +0,0 @@
From ffbfdb53681207b23bcf67dd76368ad6185ade24 Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Thu, 16 Jan 2020 07:06:09 +0100
Subject: [PATCH] Fix for CVE-2018-18074
This patch contains the fix for CVE-2018-18074 and
a subsequent regression fix combined in one.
---
sessions.py | 36 +++++++++++++++++++++++++++++-------
utils.py | 1 +
2 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/sessions.py b/sessions.py
index 6570e73..4038047 100644
--- a/sessions.py
+++ b/sessions.py
@@ -29,7 +29,7 @@ from .adapters import HTTPAdapter
from .utils import (
requote_uri, get_environ_proxies, get_netrc_auth, should_bypass_proxies,
- get_auth_from_url, rewind_body
+ get_auth_from_url, rewind_body, DEFAULT_PORTS
)
from .status_codes import codes
@@ -116,6 +116,32 @@ class SessionRedirectMixin(object):
return to_native_string(location, 'utf8')
return None
+
+ def should_strip_auth(self, old_url, new_url):
+ """Decide whether Authorization header should be removed when redirecting"""
+ old_parsed = urlparse(old_url)
+ new_parsed = urlparse(new_url)
+ if old_parsed.hostname != new_parsed.hostname:
+ return True
+ # Special case: allow http -> https redirect when using the standard
+ # ports. This isn't specified by RFC 7235, but is kept to avoid
+ # breaking backwards compatibility with older versions of requests
+ # that allowed any redirects on the same host.
+ if (old_parsed.scheme == 'http' and old_parsed.port in (80, None)
+ and new_parsed.scheme == 'https' and new_parsed.port in (443, None)):
+ return False
+
+ # Handle default port usage corresponding to scheme.
+ changed_port = old_parsed.port != new_parsed.port
+ changed_scheme = old_parsed.scheme != new_parsed.scheme
+ default_port = (DEFAULT_PORTS.get(old_parsed.scheme, None), None)
+ if (not changed_scheme and old_parsed.port in default_port
+ and new_parsed.port in default_port):
+ return False
+
+ # Standard case: root URI must match
+ return changed_port or changed_scheme
+
def resolve_redirects(self, resp, req, stream=False, timeout=None,
verify=True, cert=None, proxies=None, yield_requests=False, **adapter_kwargs):
"""Receives a Response. Returns a generator of Responses or Requests."""
@@ -232,14 +258,10 @@ class SessionRedirectMixin(object):
headers = prepared_request.headers
url = prepared_request.url
- if 'Authorization' in headers:
+ if 'Authorization' in headers and self.should_strip_auth(response.request.url, url):
# If we get redirected to a new host, we should strip out any
# authentication headers.
- original_parsed = urlparse(response.request.url)
- redirect_parsed = urlparse(url)
-
- if (original_parsed.hostname != redirect_parsed.hostname):
- del headers['Authorization']
+ del headers['Authorization']
# .netrc might have more auth for us on our new host.
new_auth = get_netrc_auth(url) if self.trust_env else None
diff --git a/utils.py b/utils.py
index 5c47de9..5695ab0 100644
--- a/utils.py
+++ b/utils.py
@@ -38,6 +38,7 @@ NETRC_FILES = ('.netrc', '_netrc')
DEFAULT_CA_BUNDLE_PATH = certs.where()
+DEFAULT_PORTS = {'http': 80, 'https': 443}
if platform.system() == 'Windows':
# provide a proxy_bypass version on Windows without DNS lookups
--
2.24.1

View File

@ -1,94 +0,0 @@
From c734f873270cf9ca414832423f7aad98443c379f Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Thu, 9 Jan 2020 11:26:24 +0100
Subject: [PATCH] CVE-2018-20060
---
poolmanager.py | 11 ++++++++++-
util/retry.py | 12 +++++++++++-
2 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/poolmanager.py b/poolmanager.py
index 4ae9174..bfa5115 100644
--- a/poolmanager.py
+++ b/poolmanager.py
@@ -312,8 +312,9 @@ class PoolManager(RequestMethods):
kw['assert_same_host'] = False
kw['redirect'] = False
+
if 'headers' not in kw:
- kw['headers'] = self.headers
+ kw['headers'] = self.headers.copy()
if self.proxy is not None and u.scheme == "http":
response = conn.urlopen(method, url, **kw)
@@ -335,6 +336,14 @@ class PoolManager(RequestMethods):
if not isinstance(retries, Retry):
retries = Retry.from_int(retries, redirect=redirect)
+ # Strip headers marked as unsafe to forward to the redirected location.
+ # Check remove_headers_on_redirect to avoid a potential network call within
+ # conn.is_same_host() which may use socket.gethostbyname() in the future.
+ if (retries.remove_headers_on_redirect
+ and not conn.is_same_host(redirect_location)):
+ for header in retries.remove_headers_on_redirect:
+ kw['headers'].pop(header, None)
+
try:
retries = retries.increment(method, url, response=response, _pool=conn)
except MaxRetryError:
diff --git a/util/retry.py b/util/retry.py
index c603cb4..0b83963 100644
--- a/util/retry.py
+++ b/util/retry.py
@@ -126,6 +126,11 @@ class Retry(object):
exhausted, to raise a MaxRetryError, or to return a response with a
response code in the 3xx range.
+ :param iterable remove_headers_on_redirect:
+ Sequence of headers to remove from the request when a response
+ indicating a redirect is returned before firing off the redirected
+ request
+
:param bool raise_on_status: Similar meaning to ``raise_on_redirect``:
whether we should raise an exception, or return a response,
if status falls in ``status_forcelist`` range and retries have
@@ -144,6 +149,8 @@ class Retry(object):
DEFAULT_METHOD_WHITELIST = frozenset([
'HEAD', 'GET', 'PUT', 'DELETE', 'OPTIONS', 'TRACE'])
+ DEFAULT_REDIRECT_HEADERS_BLACKLIST = frozenset(['Authorization'])
+
RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503])
#: Maximum backoff time.
@@ -152,7 +159,8 @@ class Retry(object):
def __init__(self, total=10, connect=None, read=None, redirect=None, status=None,
method_whitelist=DEFAULT_METHOD_WHITELIST, status_forcelist=None,
backoff_factor=0, raise_on_redirect=True, raise_on_status=True,
- history=None, respect_retry_after_header=True):
+ history=None, respect_retry_after_header=True,
+ remove_headers_on_redirect=DEFAULT_REDIRECT_HEADERS_BLACKLIST):
self.total = total
self.connect = connect
@@ -171,6 +179,7 @@ class Retry(object):
self.raise_on_status = raise_on_status
self.history = history or tuple()
self.respect_retry_after_header = respect_retry_after_header
+ self.remove_headers_on_redirect = remove_headers_on_redirect
def new(self, **kw):
params = dict(
@@ -182,6 +191,7 @@ class Retry(object):
raise_on_redirect=self.raise_on_redirect,
raise_on_status=self.raise_on_status,
history=self.history,
+ remove_headers_on_redirect=self.remove_headers_on_redirect,
)
params.update(kw)
return type(self)(**params)
--
2.24.1

View File

@ -1,43 +0,0 @@
From b40eb0f43daecc6e2e3ce47b0be49cf570d02adc Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Thu, 9 Jan 2020 11:14:58 +0100
Subject: [PATCH] CVE-2019-9740
---
util/url.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/util/url.py b/util/url.py
index 6b6f996..2784c85 100644
--- a/util/url.py
+++ b/util/url.py
@@ -1,5 +1,6 @@
from __future__ import absolute_import
from collections import namedtuple
+import re
from ..exceptions import LocationParseError
@@ -10,6 +11,8 @@ url_attrs = ['scheme', 'auth', 'host', 'port', 'path', 'query', 'fragment']
# urllib3 infers URLs without a scheme (None) to be http.
NORMALIZABLE_SCHEMES = ('http', 'https', None)
+_contains_disallowed_url_pchar_re = re.compile('[\x00-\x20\x7f]')
+from ..packages.six.moves.urllib.parse import quote
class Url(namedtuple('Url', url_attrs)):
"""
@@ -155,6 +158,10 @@ def parse_url(url):
# Empty
return Url()
+ # Prevent CVE-2019-9740.
+ # adapted from https://github.com/python/cpython/pull/12755
+ url = _contains_disallowed_url_pchar_re.sub(lambda match: quote(match.group()), url)
+
scheme = None
auth = None
host = None
--
2.24.1

View File

@ -1,26 +0,0 @@
From 54e768a6dbe3cadeb456dea37bbeaf6e1e17e87c Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Thu, 9 Jan 2020 10:47:27 +0100
Subject: [PATCH] CVE-2019-11324 Certification mishandle when error should be
thrown
---
util/ssl_.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/util/ssl_.py b/util/ssl_.py
index 32fd9ed..f9f12ff 100644
--- a/util/ssl_.py
+++ b/util/ssl_.py
@@ -319,7 +319,7 @@ def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None,
if e.errno == errno.ENOENT:
raise SSLError(e)
raise
- elif getattr(context, 'load_default_certs', None) is not None:
+ elif ssl_context is None and hasattr(context, 'load_default_certs'):
# try to load OS default certs; works well on Windows (require Python3.4+)
context.load_default_certs()
--
2.24.1

View File

@ -1,53 +0,0 @@
Backport of https://github.com/pypa/pip/pull/9827 with parts of
https://github.com/pypa/pip/pull/4690 to make it work with pip v9.0.1
diff --git a/pip/vcs/git.py b/pip/vcs/git.py
index 2187dd8..d1502f8 100644
--- a/pip/vcs/git.py
+++ b/pip/vcs/git.py
@@ -81,7 +81,7 @@ class Git(VersionControl):
and branches may need origin/ as a prefix.
Returns the SHA1 of the branch or tag if found.
"""
- revisions = self.get_short_refs(dest)
+ revisions = self.get_short_refs(dest, rev)
origin_rev = 'origin/%s' % rev
if origin_rev in revisions:
@@ -171,12 +171,20 @@ class Git(VersionControl):
['rev-parse', 'HEAD'], show_stdout=False, cwd=location)
return current_rev.strip()
- def get_full_refs(self, location):
+ def get_full_refs(self, location, pattern=''):
"""Yields tuples of (commit, ref) for branches and tags"""
- output = self.run_command(['show-ref'],
+ output = self.run_command(['show-ref', pattern],
show_stdout=False, cwd=location)
- for line in output.strip().splitlines():
- commit, ref = line.split(' ', 1)
+ for line in output.split("\n"):
+ line = line.rstrip("\r")
+ if not line:
+ continue
+ try:
+ commit, ref = line.split(' ', 1)
+ except ValueError:
+ # Include the offending line to simplify troubleshooting if
+ # this error ever occurs.
+ raise ValueError(f'unexpected show-ref line: {line!r}')
yield commit.strip(), ref.strip()
def is_ref_remote(self, ref):
@@ -200,10 +208,10 @@ class Git(VersionControl):
def get_refs(self, location):
return self.get_short_refs(location)
- def get_short_refs(self, location):
+ def get_short_refs(self, location, pattern=''):
"""Return map of named refs (branches or tags) to commit hashes."""
rv = {}
- for commit, ref in self.get_full_refs(location):
+ for commit, ref in self.get_full_refs(location, pattern):
ref_name = None
if self.is_ref_remote(ref):
ref_name = ref[len('refs/remotes/'):]

View File

@ -1,95 +0,0 @@
diff -up pip-9.0.1/pip/commands/install.py.orig pip-9.0.1/pip/commands/install.py
--- pip-9.0.1/pip/commands/install.py.orig 2016-11-06 11:49:45.000000000 -0700
+++ pip-9.0.1/pip/commands/install.py 2016-11-16 16:20:48.638906543 -0700
@@ -151,6 +151,14 @@ class InstallCommand(RequirementCommand)
"directory.")
cmd_opts.add_option(
+ '--strip-file-prefix',
+ dest='strip_file_prefix',
+ metavar='prefix',
+ default=None,
+ help="Strip given prefix from script paths in wheel RECORD."
+ )
+
+ cmd_opts.add_option(
'--prefix',
dest='prefix_path',
metavar='dir',
@@ -340,6 +348,7 @@ class InstallCommand(RequirementCommand)
global_options,
root=options.root_path,
prefix=options.prefix_path,
+ strip_file_prefix=options.strip_file_prefix,
)
possible_lib_locations = get_lib_location_guesses(
diff -up pip-9.0.1/pip/req/req_install.py.orig pip-9.0.1/pip/req/req_install.py
--- pip-9.0.1/pip/req/req_install.py.orig 2016-11-06 11:49:45.000000000 -0700
+++ pip-9.0.1/pip/req/req_install.py 2016-11-16 16:19:24.848336960 -0700
@@ -838,8 +838,7 @@ class InstallRequirement(object):
else:
return True
- def install(self, install_options, global_options=[], root=None,
- prefix=None):
+ def install(self, install_options, global_options=[], root=None, prefix=None, strip_file_prefix=None):
if self.editable:
self.install_editable(
install_options, global_options, prefix=prefix)
@@ -848,7 +847,12 @@ class InstallRequirement(object):
version = pip.wheel.wheel_version(self.source_dir)
pip.wheel.check_compatibility(version, self.name)
- self.move_wheel_files(self.source_dir, root=root, prefix=prefix)
+ self.move_wheel_files(
+ self.source_dir,
+ root=root,
+ prefix=prefix,
+ strip_file_prefix=strip_file_prefix
+ )
self.install_succeeded = True
return
@@ -1053,7 +1057,7 @@ class InstallRequirement(object):
def is_wheel(self):
return self.link and self.link.is_wheel
- def move_wheel_files(self, wheeldir, root=None, prefix=None):
+ def move_wheel_files(self, wheeldir, root=None, prefix=None, strip_file_prefix=None):
move_wheel_files(
self.name, self.req, wheeldir,
user=self.use_user_site,
@@ -1062,6 +1066,7 @@ class InstallRequirement(object):
prefix=prefix,
pycompile=self.pycompile,
isolated=self.isolated,
+ strip_file_prefix=strip_file_prefix,
)
def get_dist(self):
diff -up pip-9.0.1/pip/wheel.py.orig pip-9.0.1/pip/wheel.py
--- pip-9.0.1/pip/wheel.py.orig 2016-11-06 11:49:45.000000000 -0700
+++ pip-9.0.1/pip/wheel.py 2016-11-16 16:19:24.848336960 -0700
@@ -238,7 +238,7 @@ def get_entrypoints(filename):
def move_wheel_files(name, req, wheeldir, user=False, home=None, root=None,
- pycompile=True, scheme=None, isolated=False, prefix=None):
+ pycompile=True, scheme=None, isolated=False, prefix=None, strip_file_prefix=None):
"""Install a wheel"""
if not scheme:
@@ -521,7 +521,11 @@ if __name__ == '__main__':
writer.writerow(row)
for f in generated:
h, l = rehash(f)
- writer.writerow((normpath(f, lib_dir), h, l))
+ final_path = normpath(f, lib_dir)
+ if strip_file_prefix and final_path.startswith(strip_file_prefix):
+ final_path = os.path.join(os.sep,
+ os.path.relpath(final_path, strip_file_prefix))
+ writer.writerow((final_path, h, l))
for f in installed:
writer.writerow((installed[f], '', ''))
shutil.move(temp_record, record)

View File

@ -1,47 +0,0 @@
Minimal patch for pip
diff -rU3 pip-22.3.1-orig/src/pip/_internal/utils/unpacking.py pip-22.3.1/src/pip/_internal/utils/unpacking.py
--- a/pip/utils/__init__.py 2022-11-05 16:25:43.000000000 +0100
+++ b/pip/utils/__init__.py 2023-08-08 13:17:47.705613554 +0200
@@ -559,6 +559,13 @@
if leading:
fn = split_leading_dir(fn)[1]
path = os.path.join(location, fn)
+
+ # Call the `data` filter for its side effect (raising exception)
+ try:
+ tarfile.data_filter(member.replace(name=fn), location)
+ except tarfile.LinkOutsideDestinationError:
+ pass
+
if member.isdir():
ensure_dir(path)
elif member.issym():
Patch for vendored distlib from https://github.com/pypa/distlib/pull/201
diff --git a/distlib/util.py b/distlib/util.py
index e0622e4..4349d0b 100644
--- a/pip/_vendor/distlib/util.py
+++ b/pip/_vendor/distlib/util.py
@@ -1249,6 +1249,19 @@ def check_path(path):
for tarinfo in archive.getmembers():
if not isinstance(tarinfo.name, text_type):
tarinfo.name = tarinfo.name.decode('utf-8')
+
+ # Limit extraction of dangerous items, if this Python
+ # allows it easily. If not, just trust the input.
+ # See: https://docs.python.org/3/library/tarfile.html#extraction-filters
+ def extraction_filter(member, path):
+ """Run tarfile.tar_fillter, but raise the expected ValueError"""
+ # This is only called if the current Python has tarfile filters
+ try:
+ return tarfile.tar_filter(member, path)
+ except tarfile.FilterError as exc:
+ raise ValueError(str(exc))
+ archive.extraction_filter = extraction_filter
+
archive.extractall(dest_dir)
finally:

View File

@ -1,15 +0,0 @@
diff --git a/pip/_vendor/certifi/core.py b/pip/_vendor/certifi/core.py
index eab9d1d..9614a88 100644
--- a/pip/_vendor/certifi/core.py
+++ b/pip/_vendor/certifi/core.py
@@ -19,9 +19,7 @@ class DeprecatedBundleWarning(DeprecationWarning):
def where():
- f = os.path.dirname(__file__)
-
- return os.path.join(f, 'cacert.pem')
+ return '/etc/pki/tls/certs/ca-bundle.crt'
def old_where():

View File

@ -1,44 +0,0 @@
From 18a617e9e0f64b727938422d4f941dfddfbf5d00 Mon Sep 17 00:00:00 2001
From: Tomas Orsava <torsava@redhat.com>
Date: Tue, 14 Feb 2017 17:10:09 +0100
Subject: [PATCH] Emit a warning when running with root privileges.
---
pip/commands/install.py | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/pip/commands/install.py b/pip/commands/install.py
index 227c526..277a3d1 100644
--- a/pip/commands/install.py
+++ b/pip/commands/install.py
@@ -6,6 +6,8 @@ import os
import tempfile
import shutil
import warnings
+import sys
+from os import path
try:
import wheel
except ImportError:
@@ -193,6 +195,18 @@ class InstallCommand(RequirementCommand):
cmdoptions.resolve_wheel_no_use_binary(options)
cmdoptions.check_install_build_global(options)
+ def is_venv():
+ return hasattr(sys, 'real_prefix') or \
+ (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix)
+
+ # Check whether we have root privileges and aren't in venv/virtualenv
+ if os.getuid() == 0 and not is_venv():
+ logger.warning(
+ "WARNING: Running pip install with root privileges is "
+ "generally not a good idea. Try `%s install --user` instead."
+ % path.basename(sys.argv[0])
+ )
+
if options.as_egg:
warnings.warn(
"--egg has been deprecated and will be removed in the future. "
--
2.11.0

View File

@ -1,122 +0,0 @@
From 7917dbda14ef64a5e7fdea48383a266577484ac8 Mon Sep 17 00:00:00 2001
From: Tomas Orsava <torsava@redhat.com>
Date: Wed, 19 Aug 2020 12:51:16 +0200
Subject: [PATCH 2/2] FIX #6413 pip install <url> allow directory traversal
(tests)
---
tests/unit/test_download.py | 85 +++++++++++++++++++++++++++++++++++++
1 file changed, 85 insertions(+)
diff --git a/tests/unit/test_download.py b/tests/unit/test_download.py
index ee4b11c..15f99ec 100644
--- a/tests/unit/test_download.py
+++ b/tests/unit/test_download.py
@@ -1,5 +1,6 @@
import hashlib
import os
+import sys
from io import BytesIO
from shutil import rmtree, copy
from tempfile import mkdtemp
@@ -13,6 +14,7 @@ import pip
from pip.exceptions import HashMismatch
from pip.download import (
PipSession, SafeFileCache, path_to_url, unpack_http_url, url_to_path,
+ _download_http_url, parse_content_disposition, sanitize_content_filename,
unpack_file_url,
)
from pip.index import Link
@@ -123,6 +125,89 @@ def test_unpack_http_url_bad_downloaded_checksum(mock_unpack_file):
rmtree(download_dir)
+@pytest.mark.parametrize("filename, expected", [
+ ('dir/file', 'file'),
+ ('../file', 'file'),
+ ('../../file', 'file'),
+ ('../', ''),
+ ('../..', '..'),
+ ('/', ''),
+])
+def test_sanitize_content_filename(filename, expected):
+ """
+ Test inputs where the result is the same for Windows and non-Windows.
+ """
+ assert sanitize_content_filename(filename) == expected
+
+
+@pytest.mark.parametrize("filename, win_expected, non_win_expected", [
+ ('dir\\file', 'file', 'dir\\file'),
+ ('..\\file', 'file', '..\\file'),
+ ('..\\..\\file', 'file', '..\\..\\file'),
+ ('..\\', '', '..\\'),
+ ('..\\..', '..', '..\\..'),
+ ('\\', '', '\\'),
+])
+def test_sanitize_content_filename__platform_dependent(
+ filename,
+ win_expected,
+ non_win_expected
+):
+ """
+ Test inputs where the result is different for Windows and non-Windows.
+ """
+ if sys.platform == 'win32':
+ expected = win_expected
+ else:
+ expected = non_win_expected
+ assert sanitize_content_filename(filename) == expected
+
+
+@pytest.mark.parametrize("content_disposition, default_filename, expected", [
+ ('attachment;filename="../file"', 'df', 'file'),
+])
+def test_parse_content_disposition(
+ content_disposition,
+ default_filename,
+ expected
+):
+ actual = parse_content_disposition(content_disposition, default_filename)
+ assert actual == expected
+
+
+def test_download_http_url__no_directory_traversal(tmpdir):
+ """
+ Test that directory traversal doesn't happen on download when the
+ Content-Disposition header contains a filename with a ".." path part.
+ """
+ mock_url = 'http://www.example.com/whatever.tgz'
+ contents = b'downloaded'
+ link = Link(mock_url)
+
+ session = Mock()
+ resp = MockResponse(contents)
+ resp.url = mock_url
+ resp.headers = {
+ # Set the content-type to a random value to prevent
+ # mimetypes.guess_extension from guessing the extension.
+ 'content-type': 'random',
+ 'content-disposition': 'attachment;filename="../out_dir_file"'
+ }
+ session.get.return_value = resp
+
+ download_dir = tmpdir.join('download')
+ os.mkdir(download_dir)
+ file_path, content_type = _download_http_url(
+ link,
+ session,
+ download_dir,
+ hashes=None,
+ )
+ # The file should be downloaded to download_dir.
+ actual = os.listdir(download_dir)
+ assert actual == ['out_dir_file']
+
+
@pytest.mark.skipif("sys.platform == 'win32'")
def test_path_to_url_unix():
assert path_to_url('/tmp/file') == 'file:///tmp/file'
--
2.25.4

View File

@ -1,79 +0,0 @@
From 8044d9f2fbcb09f09a62b26ac1d8a134976bb2ac Mon Sep 17 00:00:00 2001
From: gzpan123 <gzpan123@gmail.com>
Date: Wed, 17 Apr 2019 21:25:45 +0800
Subject: [PATCH 1/2] FIX #6413 pip install <url> allow directory traversal
---
news/6413.bugfix | 3 +++
pip/download.py | 31 ++++++++++++++++++++++++++-----
2 files changed, 29 insertions(+), 5 deletions(-)
create mode 100644 news/6413.bugfix
diff --git a/news/6413.bugfix b/news/6413.bugfix
new file mode 100644
index 0000000..68d0a72
--- /dev/null
+++ b/news/6413.bugfix
@@ -0,0 +1,3 @@
+Prevent ``pip install <url>`` from permitting directory traversal if e.g.
+a malicious server sends a ``Content-Disposition`` header with a filename
+containing ``../`` or ``..\\``.
diff --git a/pip/download.py b/pip/download.py
index 039e55a..b3d169b 100644
--- a/pip/download.py
+++ b/pip/download.py
@@ -54,7 +54,8 @@ __all__ = ['get_file_content',
'is_url', 'url_to_path', 'path_to_url',
'is_archive_file', 'unpack_vcs_link',
'unpack_file_url', 'is_vcs_url', 'is_file_url',
- 'unpack_http_url', 'unpack_url']
+ 'unpack_http_url', 'unpack_url',
+ 'parse_content_disposition', 'sanitize_content_filename']
logger = logging.getLogger(__name__)
@@ -824,6 +825,29 @@ def unpack_url(link, location, download_dir=None,
write_delete_marker_file(location)
+def sanitize_content_filename(filename):
+ # type: (str) -> str
+ """
+ Sanitize the "filename" value from a Content-Disposition header.
+ """
+ return os.path.basename(filename)
+
+
+def parse_content_disposition(content_disposition, default_filename):
+ # type: (str, str) -> str
+ """
+ Parse the "filename" value from a Content-Disposition header, and
+ return the default filename if the result is empty.
+ """
+ _type, params = cgi.parse_header(content_disposition)
+ filename = params.get('filename')
+ if filename:
+ # We need to sanitize the filename to prevent directory traversal
+ # in case the filename contains ".." path parts.
+ filename = sanitize_content_filename(filename)
+ return filename or default_filename
+
+
def _download_http_url(link, session, temp_dir, hashes):
"""Download link url into temp_dir using provided session"""
target_url = link.url.split('#', 1)[0]
@@ -864,10 +888,7 @@ def _download_http_url(link, session, temp_dir, hashes):
# Have a look at the Content-Disposition header for a better guess
content_disposition = resp.headers.get('content-disposition')
if content_disposition:
- type, params = cgi.parse_header(content_disposition)
- # We use ``or`` here because we don't want to use an "empty" value
- # from the filename param.
- filename = params.get('filename') or filename
+ filename = parse_content_disposition(content_disposition, filename)
ext = splitext(filename)[1]
if not ext:
ext = mimetypes.guess_extension(content_type)
--
2.25.4

View File

@ -1,36 +0,0 @@
diff --git a/pip/utils/outdated.py b/pip/utils/outdated.py
index 2164cc3..c71539f 100644
--- a/pip/utils/outdated.py
+++ b/pip/utils/outdated.py
@@ -92,6 +92,21 @@ def load_selfcheck_statefile():
return GlobalSelfCheckState()
+def pip_installed_by_pip():
+ """Checks whether pip was installed by pip
+
+ This is used not to display the upgrade message when pip is in fact
+ installed by system package manager, such as dnf on Fedora.
+ """
+ import pkg_resources
+ try:
+ dist = pkg_resources.get_distribution('pip')
+ return (dist.has_metadata('INSTALLER') and
+ 'pip' in dist.get_metadata_lines('INSTALLER'))
+ except pkg_resources.DistributionNotFound:
+ return False
+
+
def pip_version_check(session):
"""Check for an update for pip.
@@ -141,7 +156,8 @@ def pip_version_check(session):
# Determine if our pypi_version is older
if (pip_version < remote_version and
- pip_version.base_version != remote_version.base_version):
+ pip_version.base_version != remote_version.base_version and
+ pip_installed_by_pip()):
# Advise "python -m pip" on Windows to avoid issues
# with overwriting pip.exe.
if WINDOWS:

View File

@ -1,97 +0,0 @@
diff --git a/pip/req/req_install.py b/pip/req/req_install.py
index 6911fba..8524932 100644
--- a/pip/req/req_install.py
+++ b/pip/req/req_install.py
@@ -34,7 +34,7 @@ from pip.locations import (
)
from pip.utils import (
display_path, rmtree, ask_path_exists, backup_dir, is_installable_dir,
- dist_in_usersite, dist_in_site_packages, egg_link_path,
+ dist_in_usersite, dist_in_site_packages, dist_in_install_path, egg_link_path,
call_subprocess, read_text_file, FakeFile, _make_build_dir, ensure_dir,
get_installed_version, normalize_path, dist_is_local,
)
@@ -1049,7 +1049,7 @@ class InstallRequirement(object):
"lack sys.path precedence to %s in %s" %
(existing_dist.project_name, existing_dist.location)
)
- else:
+ elif dist_in_install_path(existing_dist):
self.conflicts_with = existing_dist
return True
diff --git a/pip/req/req_set.py b/pip/req/req_set.py
index 76aec06..b93304a 100644
--- a/pip/req/req_set.py
+++ b/pip/req/req_set.py
@@ -18,7 +18,8 @@ from pip.exceptions import (InstallationError, BestVersionAlreadyInstalled,
UnsupportedPythonVersion)
from pip.req.req_install import InstallRequirement
from pip.utils import (
- display_path, dist_in_usersite, ensure_dir, normalize_path)
+ display_path, dist_in_usersite, dist_in_install_path, ensure_dir,
+ normalize_path)
from pip.utils.hashes import MissingHashes
from pip.utils.logging import indent_log
from pip.utils.packaging import check_dist_requires_python
@@ -437,10 +438,12 @@ class RequirementSet(object):
if not best_installed:
# don't uninstall conflict if user install and
- # conflict is not user install
+ # conflict is not user install or conflict lives
+ # in a different path (/usr/lib vs /usr/local/lib/)
if not (self.use_user_site and not
- dist_in_usersite(req_to_install.satisfied_by)):
- req_to_install.conflicts_with = \
+ dist_in_usersite(req_to_install.satisfied_by) or not
+ dist_in_install_path(req_to_install.satisfied_by)):
+ req_to_install.conflicts_with = \
req_to_install.satisfied_by
req_to_install.satisfied_by = None
@@ -644,10 +647,12 @@ class RequirementSet(object):
if req_to_install.satisfied_by:
if self.upgrade or self.ignore_installed:
# don't uninstall conflict if user install and
- # conflict is not user install
+ # conflict is not user install or conflict lives
+ # in a different path (/usr/lib vs /usr/local/lib/)
if not (self.use_user_site and not
dist_in_usersite(
- req_to_install.satisfied_by)):
+ req_to_install.satisfied_by) or not
+ dist_in_install_path(req_to_install.satisfied_by)):
req_to_install.conflicts_with = \
req_to_install.satisfied_by
req_to_install.satisfied_by = None
diff --git a/pip/utils/__init__.py b/pip/utils/__init__.py
index 815bd33..0ed59f7 100644
--- a/pip/utils/__init__.py
+++ b/pip/utils/__init__.py
@@ -22,7 +22,7 @@ from pip.exceptions import InstallationError
from pip.compat import console_to_str, expanduser, stdlib_pkgs
from pip.locations import (
site_packages, user_site, running_under_virtualenv, virtualenv_no_global,
- write_delete_marker_file,
+ write_delete_marker_file, distutils_scheme,
)
from pip._vendor import pkg_resources
from pip._vendor.six.moves import input
@@ -315,6 +315,16 @@ def dist_in_site_packages(dist):
).startswith(normalize_path(site_packages))
+def dist_in_install_path(dist):
+ """
+ Return True if given Distribution is installed in
+ path matching distutils_scheme layout.
+ """
+ norm_path = normalize_path(dist_location(dist))
+ return norm_path.startswith(normalize_path(
+ distutils_scheme("")['purelib'].split('python')[0]))
+
+
def dist_is_editable(dist):
"""Is distribution an editable install?"""
for path_item in sys.path:

View File

@ -1,91 +0,0 @@
From b97ef609100fbdd5895dab48cdab578dfeba396c Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Fri, 10 Sep 2021 13:38:40 +0200
Subject: [PATCH 1/2] Implement handling of yanked_reason from the HTML anchor
---
pip/index.py | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/pip/index.py b/pip/index.py
index f653f6e6a..ced52ce5a 100644
--- a/pip/index.py
+++ b/pip/index.py
@@ -865,7 +865,11 @@ class HTMLPage(object):
)
pyrequire = anchor.get('data-requires-python')
pyrequire = unescape(pyrequire) if pyrequire else None
- yield Link(url, self, requires_python=pyrequire)
+ yanked_reason = anchor.get('data-yanked', default=None)
+ # Empty or valueless attribute are both parsed as empty string
+ if yanked_reason is not None:
+ yanked_reason = unescape(yanked_reason)
+ yield Link(url, self, requires_python=pyrequire, yanked_reason=yanked_reason)
_clean_re = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I)
@@ -879,7 +883,7 @@ class HTMLPage(object):
class Link(object):
- def __init__(self, url, comes_from=None, requires_python=None):
+ def __init__(self, url, comes_from=None, requires_python=None, yanked_reason=None):
"""
Object representing a parsed link from https://pypi.python.org/simple/*
@@ -900,6 +904,8 @@ class Link(object):
self.url = url
self.comes_from = comes_from
self.requires_python = requires_python if requires_python else None
+ self.yanked_reason = yanked_reason
+ self.yanked = yanked_reason is not None
def __str__(self):
if self.requires_python:
--
2.31.1
From d8dc6ee5d6809736dce43dc1e57d497f9ff91f26 Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Fri, 10 Sep 2021 13:43:22 +0200
Subject: [PATCH 2/2] Skip all yanked candidates if possible
---
pip/index.py | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/pip/index.py b/pip/index.py
index ced52ce5a..823bbaf7d 100644
--- a/pip/index.py
+++ b/pip/index.py
@@ -489,6 +489,27 @@ class PackageFinder(object):
if applicable_candidates:
best_candidate = max(applicable_candidates,
key=self._candidate_sort_key)
+ # If we cannot find a non-yanked candidate,
+ # use the best one and print a warning about it.
+ # Otherwise, try to find another best candidate, ignoring
+ # all the yanked releases.
+ if getattr(best_candidate.location, "yanked", False):
+ nonyanked_candidates = [
+ c for c in applicable_candidates
+ if not getattr(c.location, "yanked", False)
+ ]
+
+ if set(nonyanked_candidates):
+ best_candidate = max(nonyanked_candidates,
+ key=self._candidate_sort_key)
+ else:
+ warning_message = (
+ "WARNING: The candidate selected for download or install "
+ "is a yanked version: '{}' candidate (version {} at {})"
+ ).format(best_candidate.project, best_candidate.version, best_candidate.location)
+ if best_candidate.location.yanked_reason:
+ warning_message += "\nReason for being yanked: {}".format(best_candidate.location.yanked_reason)
+ logger.warning(warning_message)
else:
best_candidate = None
--
2.31.1

View File

@ -1,688 +0,0 @@
%bcond_with bootstrap
%bcond_with tests
%bcond_without doc
%global srcname pip
%global python3_wheelname %{srcname}-%{version}-py2.py3-none-any.whl
%if %{without bootstrap}
%global python3_wheeldir %{_datadir}/python3-wheels
%endif
%global bashcompdir %(b=$(pkg-config --variable=completionsdir bash-completion 2>/dev/null); echo ${b:-%{_sysconfdir}/bash_completion.d})
Name: python-%{srcname}
# When updating, update the bundled libraries versions bellow!
Version: 9.0.3
Release: 24%{?dist}
Summary: A tool for installing and managing Python packages
Group: Development/Libraries
# We bundle a lot of libraries with pip, which itself is under MIT license.
# Here is the list of the libraries with corresponding licenses:
# appdirs: MIT
# CacheControl: ASL 2.0
# certifi: MPLv2.0
# chardet: LGPLv2
# colorama: BSD
# distlib: Python
# distro: ASL 2.0
# html5lib: MIT
# idna: BSD
# ipaddress: Python
# lockfile: MIT
# packaging: ASL 2.0 or BSD
# progress: ISC
# pyparsing: MIT
# requests: ASL 2.0
# retrying: ASL 2.0
# urllib3: MIT
# six: MIT
# urllib3: MIT
# webencodings: BSD
License: MIT and Python and ASL 2.0 and BSD and ISC and LGPLv2 and MPLv2.0 and (ASL 2.0 or BSD)
URL: http://www.pip-installer.org
Source0: https://files.pythonhosted.org/packages/source/p/%{srcname}/%{srcname}-%{version}.tar.gz
BuildArch: noarch
%if %{with tests}
BuildRequires: git
BuildRequires: bzr
%endif
# to get tests:
# git clone https://github.com/pypa/pip && cd pip
# git checkout 9.0.1 && tar -czvf ../pip-9.0.1-tests.tar.gz tests/
%if %{with tests}
Source1: pip-%{version}-tests.tar.gz
%endif
# Patch until the following issue gets implemented upstream:
# https://github.com/pypa/pip/issues/1351
Patch0: allow-stripping-given-prefix-from-wheel-RECORD-files.patch
# Downstream only patch
# Emit a warning to the user if pip install is run with root privileges
# Issue upstream: https://github.com/pypa/pip/issues/4288
Patch1: emit-a-warning-when-running-with-root-privileges.patch
# Prevent removing of the system packages installed under /usr/lib
# when pip install -U is executed.
# https://bugzilla.redhat.com/show_bug.cgi?id=1626408
# Author: Michal Cyprian
Patch2: remove-existing-dist-only-if-path-conflicts.patch
# Do not show the "new version of pip" warning outside of venv
# Upstream issue: https://github.com/pypa/pip/issues/5346
# Fedora bug: https://bugzilla.redhat.com/show_bug.cgi?id=1573755
Patch3: pip-nowarn-upgrade.patch
# Use the system level root certificate instead of the one bundled in certifi
# https://bugzilla.redhat.com/show_bug.cgi?id=1655255
Patch4: dummy-certifi.patch
# Patch for CVE in the bundled urllib3
# CVE-2018-20060 Cross-host redirect does not remove Authorization header allow for credential exposure
# https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2018-20060
Patch5: CVE-2018-20060.patch
# Patch for CVE in the bundled urllib3
# CVE-2019-11236 CRLF injection due to not encoding the '\r\n' sequence leading to possible attack on internal service
# https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2019-11236
Patch6: CVE-2019-11236.patch
# Patch for CVE in the bundled urllib3
# CVE-2019-11324 Certification mishandle when error should be thrown
# https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2019-11324
Patch7: CVE-2019-11324.patch
# Patch for CVE in the bundled requests
# CVE-2018-18074 Redirect from HTTPS to HTTP does not remove Authorization header
# This patch fixes both the CVE
# https://bugzilla.redhat.com/show_bug.cgi?id=1643829
# and the subsequent regression
# https://github.com/psf/requests/pull/4851
Patch8: CVE-2018-18074.patch
# Patch for pip install <url> allow directory traversal, leading to arbitrary file write
# - Upstream PR: https://github.com/pypa/pip/pull/6418/files
# - Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1868016
# Patch9 fixes the issue
# Patch10 adds unit tests for the issue
Patch9: pip-directory-traversal-security-issue.patch
Patch10: pip-directory-traversal-security-issue-tests.patch
# Patch for CVE-2021-3572 - pip incorrectly handled unicode separators in git references
# The patch is adjusted for older pip where it's necessary to also switch
# the way pip gets revisions from git
# Upstream PR: https://github.com/pypa/pip/pull/9827
# Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1962856
Patch11: CVE-2021-3572.patch
# Downstream-only implementation of support of yanked releases
# PEP 592 - Adding "Yank" Support to the Simple API:
# https://www.python.org/dev/peps/pep-0592/
# Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2000135
Patch12: skip_yanked_releases.patch
# CVE-2007-4559, PEP-721, PEP-706: Use tarfile.data_filter for extracting
# - Minimal downstream-only patch, to be replaced by upstream solution
# proposed in https://github.com/pypa/pip/pull/12214
# - Patch for vendored distlib, accepted upstream:
# https://github.com/pypa/distlib/pull/201
Patch13: cve-2007-4559-tarfile.patch
%global _description \
pip is a package management system used to install and manage software packages \
written in Python. Many packages can be found in the Python Package Index \
(PyPI). pip is a recursive acronym that can stand for either "Pip Installs \
Packages" or "Pip Installs Python".
%description %_description
%package -n platform-python-%{srcname}
Summary: A tool for installing and managing Python3 packages
Group: Development/Libraries
Conflicts: python%{python3_pkgversion}-pip < 9.0.3-5%{?dist}
Obsoletes: python%{python3_pkgversion}-pip < 9.0.3-6%{?dist}
BuildRequires: python%{python3_pkgversion}-devel
BuildRequires: python%{python3_pkgversion}-setuptools
BuildRequires: bash-completion
%if %{with tests}
BuildRequires: python%{python3_pkgversion}-mock
BuildRequires: python%{python3_pkgversion}-pytest
BuildRequires: python%{python3_pkgversion}-pretend
BuildRequires: python%{python3_pkgversion}-freezegun
BuildRequires: python%{python3_pkgversion}-pytest-capturelog
BuildRequires: python%{python3_pkgversion}-scripttest
BuildRequires: python%{python3_pkgversion}-virtualenv
%endif
%if %{without bootstrap}
BuildRequires: python%{python3_pkgversion}-pip
BuildRequires: python%{python3_pkgversion}-wheel
%endif
Requires: platform-python-setuptools
BuildRequires: ca-certificates
Requires: ca-certificates
# pip has to require explicit version of platform-python that provides
# filters in tarfile module (fix for CVE-2007-4559).
Requires: platform-python >= 3.6.8-55
# Virtual provides for the packages bundled by pip.
# See the python2 list above for instructions.
Provides: bundled(python3dist(appdirs)) = 1.4.0
Provides: bundled(python3dist(cachecontrol)) = 0.11.7
Provides: bundled(python3dist(colorama)) = 0.3.7
Provides: bundled(python3dist(distlib)) = 0.2.4
Provides: bundled(python3dist(distro)) = 1.0.1
Provides: bundled(python3dist(html5lib)) = 1.0b10
Provides: bundled(python3dist(ipaddress) = 1.0.17
Provides: bundled(python3dist(lockfile)) = 0.12.2
Provides: bundled(python3dist(packaging)) = 16.8
Provides: bundled(python3dist(setuptools)) = 28.8.0
Provides: bundled(python3dist(progress)) = 1.2
Provides: bundled(python3dist(pyparsing)) = 2.1.10
Provides: bundled(python3dist(requests)) = 2.11.1
Provides: bundled(python3dist(retrying)) = 1.3.3
Provides: bundled(python3dist(six)) = 1.10.0
Provides: bundled(python3dist(webencodings)) = 0.5
# Bundled within the requests bundle
Provides: bundled(python3dist(chardet)) = 2.3.0
Provides: bundled(python3dist(urllib3)) = 1.16
%description -n platform-python-%{srcname} %_description
%package -n python%{python3_pkgversion}-%{srcname}
Summary: A tool for installing and managing Python3 packages
Group: Development/Libraries
Requires: platform-python-pip = %{version}-%{release}
Requires: python36
%{?python_provide:%python_provide python%{python3_pkgversion}-%{srcname}}
%description -n python%{python3_pkgversion}-%{srcname} %_description
%if %{with doc}
%package doc
Summary: A documentation for a tool for installing and managing Python packages
BuildRequires: python%{python3_pkgversion}-sphinx
%description doc
A documentation for a tool for installing and managing Python packages
%endif
%if %{without bootstrap}
%package -n python3-%{srcname}-wheel
Summary: The pip wheel
# Older Python does not provide tarfile filters (fix for CVE-2007-4559).
Conflicts: platform-python < 3.6.8-55
# Virtual provides for the packages bundled by pip.
# You can find the versions in pip/_vendor/vendor.txt file.
Provides: bundled(python3dist(appdirs)) = 1.4.0
Provides: bundled(python3dist(cachecontrol)) = 0.11.7
Provides: bundled(python3dist(colorama)) = 0.3.7
Provides: bundled(python3dist(distlib)) = 0.2.4
Provides: bundled(python3dist(distro)) = 1.0.1
Provides: bundled(python3dist(html5lib)) = 1.0b10
Provides: bundled(python3dist(ipaddress) = 1.0.17
Provides: bundled(python3dist(lockfile)) = 0.12.2
Provides: bundled(python3dist(packaging)) = 16.8
Provides: bundled(python3dist(setuptools)) = 28.8.0
Provides: bundled(python3dist(progress)) = 1.2
Provides: bundled(python3dist(pyparsing)) = 2.1.10
Provides: bundled(python3dist(requests)) = 2.11.1
Provides: bundled(python3dist(retrying)) = 1.3.3
Provides: bundled(python3dist(six)) = 1.10.0
Provides: bundled(python3dist(webencodings)) = 0.5
# Bundled within the requests bundle
Provides: bundled(python3dist(chardet)) = 2.3.0
Provides: bundled(python3dist(urllib3)) = 1.16
%description -n python3-%{srcname}-wheel
A Python wheel of pip to use with venv.
%endif
%prep
%setup -q -n %{srcname}-%{version}
%if %{with tests}
tar -xf %{SOURCE1}
%endif
%patch0 -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
# Patching of bundled libraries
pushd pip/_vendor/urllib3
%patch5 -p1
%patch6 -p1
%patch7 -p1
popd
pushd pip/_vendor/requests
%patch8 -p1
popd
%patch9 -p1
%if %{with tests}
%patch10 -p1
%endif
%patch11 -p1
%patch12 -p1
%patch13 -p1
# this goes together with patch4
rm pip/_vendor/certifi/*.pem
rm pip/_vendor/requests/*.pem
sed -i '/\.pem$/d' pip.egg-info/SOURCES.txt
sed -i '1d' pip/__init__.py
# Remove ordereddict as it is only required for python <= 2.6
rm pip/_vendor/ordereddict.py
# Remove windows executable binaries
rm -v pip/_vendor/distlib/*.exe
sed -i '/\.exe/d' setup.py
# Backports for Python 2
rm pip/_vendor/distlib/_backport/tarfile.py
rm pip/_vendor/distlib/_backport/shutil.py
%build
%if %{without bootstrap}
%py3_build_wheel
%else
%py3_build
%endif
%if %{with doc}
pushd docs
make html
make man
rm _build/html/.buildinfo
popd
%endif
%install
%if %{without bootstrap}
%py3_install_wheel %{python3_wheelname}
%else
%py3_install
%endif
rm %{buildroot}%{_bindir}/pip
%if %{with doc}
install -d %{buildroot}%{_mandir}/man1
install -pm0644 docs/_build/man/*.1 %{buildroot}%{_mandir}/man1/pip3.1
%endif # with doc
mkdir -p %{buildroot}%{bashcompdir}
PYTHONPATH=%{buildroot}%{python3_sitelib} \
%{buildroot}%{_bindir}/pip3 completion --bash \
> %{buildroot}%{bashcompdir}/pip3
sed -i -e "s/^\\(complete.*\\) pip\$/\\1 pip3 pip-3 pip3.6 pip-3.6/" \
-e s/_pip_completion/_pip3_completion/ \
%{buildroot}%{bashcompdir}/pip3
# Provide symlinks to executables to comply with Fedora guidelines for Python
mv %{buildroot}%{_bindir}/pip3 %{buildroot}%{_bindir}/pip%{python3_version}
ln -s ./pip%{python3_version} %{buildroot}%{_bindir}/pip-%{python3_version}
# Change shebang in /usr/bin/pip3.6 to /usr/bin/python3.6
pathfix.py -i /usr/bin/python%{python3_version} -np %{buildroot}%{_bindir}/pip%{python3_version}
# Make sure the INSTALLER is not pip, otherwise pip-nowarn-upgrade.patch
# (Patch3) won't work
echo rpm > %{buildroot}%{python3_sitelib}/pip-%{version}.dist-info/INSTALLER
%if %{without bootstrap}
mkdir -p %{buildroot}%{python3_wheeldir}
install -p dist/%{python3_wheelname} -t %{buildroot}%{python3_wheeldir}
%endif
%if %{with tests}
%check
py.test-%{python3_version} -m 'not network'
%endif
%files -n platform-python-%{srcname}
%license LICENSE.txt
%doc README.rst
%if %{with doc}
%{_mandir}/man1/pip3.*
%endif
%{python3_sitelib}/pip*
%files -n python%{python3_pkgversion}-%{srcname}
%license LICENSE.txt
%doc README.rst
# The pip3 binary is created using alternatives
# defined in the python36 package
%{_bindir}/pip%{python3_version}
%{_bindir}/pip-%{python3_version}
%dir %{bashcompdir}
%{bashcompdir}/pip*
%if %{with doc}
%files doc
%license LICENSE.txt
%doc README.rst
%doc docs/_build/html
%endif # with doc
%if %{without bootstrap}
%files -n python3-%{srcname}-wheel
%license LICENSE.txt
# we own the dir for simplicity
%dir %{python3_wheeldir}/
%{python3_wheeldir}/%{python3_wheelname}
%endif
%changelog
* Wed Feb 14 2024 Lumír Balhar <lbalhar@redhat.com> - 9.0.3-24
- Require Python with tarfile filters
Resolves: RHEL-25446
* Tue Aug 08 2023 Petr Viktorin <pviktori@redhat.com> - 9.0.3-23
- Use tarfile.data_filter for extracting (CVE-2007-4559, PEP-721, PEP-706)
Resolves: RHBZ#2218241
* Wed Oct 06 2021 Charalampos Stratakis <cstratak@redhat.com> - 9.0.3-22
- Remove bundled windows executables
- Resolves: rhbz#2006788
* Tue Oct 05 2021 Lumír Balhar <lbalhar@redhat.com> - 9.0.3-21
- Support of yanked releases
Resolves: rhbz#2000135
* Mon Jun 07 2021 Lumír Balhar <lbalhar@redhat.com> - 9.0.3-20
- Fix for CVE-2021-3572 - pip incorrectly handled unicode separators in git references
Resolves: rhbz#1962856
* Fri Jan 08 2021 Lumír Balhar <lbalhar@redhat.com> - 9.0.3-19
- Fix bash completion files and simplify spec
Resolves: rhbz#1904478
* Wed Aug 19 2020 Tomas Orsava <torsava@redhat.com> - 9.0.3-18
- Patch for pip install <url> allow directory traversal, leading to arbitrary file write
Resolves: rhbz#1868016
* Wed Mar 04 2020 Charalampos Stratakis <cstratak@redhat.com> - 9.0.3-17
- Remove unused CA bundle from the bundled requests library
Resolves: rhbz#1775200
* Mon Jan 13 2020 Lumír Balhar <lbalhar@redhat.com> - 9.0.3-16
- Add four new patches for CVEs in bundled urllib3 and requests
CVE-2018-20060, CVE-2019-11236, CVE-2019-11324, CVE-2018-18074
Resolves: rhbz#1649153
Resolves: rhbz#1700824
Resolves: rhbz#1702473
Resolves: rhbz#1643829
* Thu Jun 06 2019 Charalampos Stratakis <cstratak@redhat.com> - 9.0.3-15
- Create python-pip-wheel package with the wheel
Resolves: rhbz#1718031
* Wed Mar 13 2019 Lumír Balhar <lbalhar@redhat.com> - 9.0.3-14
- Move bash completion files from platform-python- to python3- subpackage
- resolves: rhbz#1664749
* Mon Dec 03 2018 Miro Hrončok <mhroncok@redhat.com> - 9.0.3-13
- Use the system level root certificate instead of the one bundled in certifi
- Resolves: rhbz#1655255
* Wed Nov 28 2018 Tomas Orsava <torsava@redhat.com> - 9.0.3-12
- Do not show the "new version of pip" warning outside of venv
- Resolves: rhbz#1656171
* Mon Nov 19 2018 Victor Stinner <vstinner@redhat.com> - 9.0.3-11
- Prevent removing of the system packages installed under /usr/lib
when pip install -U is executed. Patch by Michal Cyprian.
Resolves: rhbz#1626408.
* Fri Nov 16 2018 Tomas Orsava <torsava@redhat.com> - 9.0.3-10
- Bump the NVR so it's higher than previous builds of python3-pip that have
mistakenly gotten into the python27 module build when we were dealing with an
MBS filtering problem. See BZ#1650568.
- Resolves: rhbz#1638836
* Mon Nov 12 2018 Lumír Balhar <lbalhar@redhat.com> - 9.0.3-6
- python3-pip requires python36 and obsoletes previous version
where python3- and platform-python- were in one package
- Resolves: rhbz#1638836
* Mon Oct 22 2018 Tomas Orsava <torsava@redhat.com> - 9.0.3-5
- Split part of the python3-pip package into platform-python-pip
- python3-pip will only contain binaries in /usr/bin
- Resolves: rhbz#1638836
* Mon Aug 06 2018 Petr Viktorin <pviktori@redhat.com> - 9.0.3-4
- Remove the python2 subpackage
- Remove unversioned executables (only *-3.6 should be provided)
* Mon Aug 06 2018 Charalampos Stratakis <cstratak@redhat.com> - 9.0.3-3
- Correct license information
* Mon Jun 25 2018 Petr Viktorin <pviktori@redhat.com> - 9.0.3-2
- Don't build the python2 subpackage
https://bugzilla.redhat.com/show_bug.cgi?id=1594335
* Thu Mar 29 2018 Charalampos Stratakis <cstratak@redhat.com> - 9.0.3-1
- Update to 9.0.3
* Wed Feb 21 2018 Lumír Balhar <lbalhar@redhat.com> - 9.0.1-16
- Include built HTML documentation (in the new -doc subpackage) and man page
* Fri Feb 09 2018 Fedora Release Engineering <releng@fedoraproject.org> - 9.0.1-15
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
* Mon Dec 04 2017 Charalampos Stratakis <cstratak@redhat.com> - 9.0.1-14
- Reintroduce the ipaddress module in the python3 subpackage.
* Mon Nov 20 2017 Charalampos Stratakis <cstratak@redhat.com> - 9.0.1-13
- Add virtual provides for the bundled libraries. (rhbz#1096912)
* Tue Aug 29 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-12
- Switch macros to bcond's and make Python 2 optional to facilitate building
the Python 2 and Python 3 modules
* Thu Jul 27 2017 Fedora Release Engineering <releng@fedoraproject.org> - 9.0.1-11
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
* Tue May 23 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-10
- Modernized package descriptions
Resolves: rhbz#1452568
* Tue Mar 21 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-9
- Fix typo in the sudo pip warning
* Fri Mar 03 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-8
- Patch 1 update: No sudo pip warning in venv or virtualenv
* Thu Feb 23 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-7
- Patch 1 update: Customize the warning with the proper version of the pip
command
* Tue Feb 14 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-6
- Added patch 1: Emit a warning when running with root privileges
* Sat Feb 11 2017 Fedora Release Engineering <releng@fedoraproject.org> - 9.0.1-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
* Mon Jan 02 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-4
- Provide symlinks to executables to comply with Fedora guidelines for Python
Resolves: rhbz#1406922
* Fri Dec 09 2016 Charalampos Stratakis <cstratak@redhat.com> - 9.0.1-3
- Rebuild for Python 3.6 with wheel
* Fri Dec 09 2016 Charalampos Stratakis <cstratak@redhat.com> - 9.0.1-2
- Rebuild for Python 3.6 without wheel
* Fri Nov 18 2016 Orion Poplawski <orion@cora.nwra.com> - 9.0.1-1
- Update to 9.0.1
* Fri Nov 18 2016 Orion Poplawski <orion@cora.nwra.com> - 8.1.2-5
- Enable EPEL Python 3 builds
- Use new python macros
- Cleanup spec
* Fri Aug 05 2016 Tomas Orsava <torsava@redhat.com> - 8.1.2-4
- Updated the test sources
* Fri Aug 05 2016 Tomas Orsava <torsava@redhat.com> - 8.1.2-3
- Moved python-pip into the python2-pip subpackage
- Added the python_provide macro
* Tue Jul 19 2016 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 8.1.2-2
- https://fedoraproject.org/wiki/Changes/Automatic_Provides_for_Python_RPM_Packages
* Tue May 17 2016 Tomas Orsava <torsava@redhat.com> - 8.1.2-1
- Update to 8.1.2
- Moved to a new PyPI URL format
- Updated the prefix-stripping patch because of upstream changes in pip/wheel.py
* Mon Feb 22 2016 Slavek Kabrda <bkabrda@redhat.com> - 8.0.2-1
- Update to 8.0.2
* Thu Feb 04 2016 Fedora Release Engineering <releng@fedoraproject.org> - 7.1.0-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
* Wed Oct 14 2015 Robert Kuska <rkuska@redhat.com> - 7.1.0-3
- Rebuilt for Python3.5 rebuild
- With wheel set to 1
* Tue Oct 13 2015 Robert Kuska <rkuska@redhat.com> - 7.1.0-2
- Rebuilt for Python3.5 rebuild
* Wed Jul 01 2015 Slavek Kabrda <bkabrda@redhat.com> - 7.1.0-1
- Update to 7.1.0
* Tue Jun 30 2015 Ville Skyttä <ville.skytta@iki.fi> - 7.0.3-3
- Install bash completion
- Ship LICENSE.txt as %%license where available
* Thu Jun 18 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 7.0.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
* Thu Jun 04 2015 Matej Stuchlik <mstuchli@redhat.com> - 7.0.3-1
- Update to 7.0.3
* Fri Mar 06 2015 Matej Stuchlik <mstuchli@redhat.com> - 6.0.8-1
- Update to 6.0.8
* Thu Dec 18 2014 Slavek Kabrda <bkabrda@redhat.com> - 1.5.6-5
- Only enable tests on Fedora.
* Mon Dec 01 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.6-4
- Add tests
- Add patch skipping tests requiring Internet access
* Tue Nov 18 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.6-3
- Added patch for local dos with predictable temp dictionary names
(http://seclists.org/oss-sec/2014/q4/655)
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.5.6-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
* Sun May 25 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.6-1
- Update to 1.5.6
* Fri Apr 25 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.4-4
- Rebuild as wheel for Python 3.4
* Thu Apr 24 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.4-3
- Disable build_wheel
* Thu Apr 24 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.4-2
- Rebuild as wheel for Python 3.4
* Mon Apr 07 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.4-1
- Updated to 1.5.4
* Mon Oct 14 2013 Tim Flink <tflink@fedoraproject.org> - 1.4.1-1
- Removed patch for CVE 2013-2099 as it has been included in the upstream 1.4.1 release
- Updated version to 1.4.1
* Sun Aug 04 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.3.1-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
* Tue Jul 16 2013 Toshio Kuratomi <toshio@fedoraproject.org> - 1.3.1-4
- Fix for CVE 2013-2099
* Thu May 23 2013 Tim Flink <tflink@fedoraproject.org> - 1.3.1-3
- undo python2 executable rename to python-pip. fixes #958377
- fix summary to match upstream
* Mon May 06 2013 Kevin Kofler <Kevin@tigcc.ticalc.org> - 1.3.1-2
- Fix main package Summary, it's for Python 2, not 3 (#877401)
* Fri Apr 26 2013 Jon Ciesla <limburgher@gmail.com> - 1.3.1-1
- Update to 1.3.1, fix for CVE-2013-1888.
* Thu Feb 14 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.2.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
* Tue Oct 09 2012 Tim Flink <tflink@fedoraproject.org> - 1.2.1-2
- Fixing files for python3-pip
* Thu Oct 04 2012 Tim Flink <tflink@fedoraproject.org> - 1.2.1-1
- Update to upstream 1.2.1
- Change binary from pip-python to python-pip (RHBZ#855495)
- Add alias from python-pip to pip-python, to be removed at a later date
* Tue May 15 2012 Tim Flink <tflink@fedoraproject.org> - 1.1.0-1
- Update to upstream 1.1.0
* Sat Jan 14 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.0.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
* Sat Oct 22 2011 Tim Flink <tflink@fedoraproject.org> - 1.0.2-1
- update to 1.0.2 and added python3 subpackage
* Wed Jun 22 2011 Tim Flink <tflink@fedoraproject.org> - 0.8.3-1
- update to 0.8.3 and project home page
* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.8.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
* Mon Dec 20 2010 Luke Macken <lmacken@redhat.com> - 0.8.2-1
- update to 0.8.2 of pip
* Mon Aug 30 2010 Peter Halliday <phalliday@excelsiorsystems.net> - 0.8-1
- update to 0.8 of pip
* Thu Jul 22 2010 David Malcolm <dmalcolm@redhat.com> - 0.7.2-5
- Rebuilt for https://fedoraproject.org/wiki/Features/Python_2.7/MassRebuild
* Wed Jul 7 2010 Peter Halliday <phalliday@excelsiorsystems.net> - 0.7.2-1
- update to 0.7.2 of pip
* Sun May 23 2010 Peter Halliday <phalliday@excelsiorsystems.net> - 0.7.1-1
- update to 0.7.1 of pip
* Fri Jan 1 2010 Peter Halliday <phalliday@excelsiorsystems.net> - 0.6.1.4
- fix dependency issue
* Fri Dec 18 2009 Peter Halliday <phalliday@excelsiorsystems.net> - 0.6.1-2
- fix spec file
* Thu Dec 17 2009 Peter Halliday <phalliday@excelsiorsystems.net> - 0.6.1-1
- upgrade to 0.6.1 of pip
* Mon Aug 31 2009 Peter Halliday <phalliday@excelsiorsystems.net> - 0.4-1
- Initial package

View File

@ -0,0 +1,85 @@
From 1819805f2019c731bcaefd6b12fd814790f88fcd Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Tue, 19 Mar 2024 12:43:07 +0100
Subject: [PATCH] cve-2007-4559-tarfile
Minimal patch for pip
---
src/pip/_internal/utils/unpacking.py | 7 +++++++
src/pip/_vendor/distlib/util.py | 13 +++++++++++++
tests/unit/test_utils_unpacking.py | 17 +++++++++++++++++
3 files changed, 37 insertions(+)
diff --git a/src/pip/_internal/utils/unpacking.py b/src/pip/_internal/utils/unpacking.py
index 5f63f97..c31542f 100644
--- a/src/pip/_internal/utils/unpacking.py
+++ b/src/pip/_internal/utils/unpacking.py
@@ -184,6 +184,13 @@ def untar_file(filename: str, location: str) -> None:
"outside target directory ({})"
)
raise InstallationError(message.format(filename, path, location))
+
+ # Call the `data` filter for its side effect (raising exception)
+ try:
+ tarfile.data_filter(member.replace(name=fn), location)
+ except tarfile.LinkOutsideDestinationError:
+ pass
+
if member.isdir():
ensure_dir(path)
elif member.issym():
diff --git a/src/pip/_vendor/distlib/util.py b/src/pip/_vendor/distlib/util.py
index 80bfc86..7e0941a 100644
--- a/src/pip/_vendor/distlib/util.py
+++ b/src/pip/_vendor/distlib/util.py
@@ -1249,6 +1249,19 @@ def unarchive(archive_filename, dest_dir, format=None, check=True):
for tarinfo in archive.getmembers():
if not isinstance(tarinfo.name, text_type):
tarinfo.name = tarinfo.name.decode('utf-8')
+
+ # Limit extraction of dangerous items, if this Python
+ # allows it easily. If not, just trust the input.
+ # See: https://docs.python.org/3/library/tarfile.html#extraction-filters
+ def extraction_filter(member, path):
+ """Run tarfile.tar_fillter, but raise the expected ValueError"""
+ # This is only called if the current Python has tarfile filters
+ try:
+ return tarfile.tar_filter(member, path)
+ except tarfile.FilterError as exc:
+ raise ValueError(str(exc))
+ archive.extraction_filter = extraction_filter
+
archive.extractall(dest_dir)
finally:
diff --git a/tests/unit/test_utils_unpacking.py b/tests/unit/test_utils_unpacking.py
index ccb7a30..05324ad 100644
--- a/tests/unit/test_utils_unpacking.py
+++ b/tests/unit/test_utils_unpacking.py
@@ -171,6 +171,23 @@ class TestUnpackArchives:
test_tar = self.make_tar_file("test_tar.tar", files)
untar_file(test_tar, self.tempdir)
+ def test_unpack_tar_filter(self) -> None:
+ """
+ Test that the tarfile.data_filter is used to disallow dangerous
+ behaviour (PEP-721)
+ """
+ test_tar = os.path.join(self.tempdir, "test_tar_filter.tar")
+ with tarfile.open(test_tar, "w") as mytar:
+ file_tarinfo = tarfile.TarInfo("bad-link")
+ file_tarinfo.type = tarfile.SYMTYPE
+ file_tarinfo.linkname = "../../../../pwn"
+ mytar.addfile(file_tarinfo, io.BytesIO(b""))
+ with pytest.raises(InstallationError) as e:
+ untar_file(test_tar, self.tempdir)
+
+ assert "is outside the destination" in str(e.value)
+
+
def test_unpack_tar_unicode(tmpdir: Path) -> None:
test_tar = tmpdir / "test.tar"
--
2.44.0

View File

@ -0,0 +1,33 @@
From ca24e4bfa60cec8341ccf40000a41bc9592713df Mon Sep 17 00:00:00 2001
From: Karolina Surma <ksurma@redhat.com>
Date: Mon, 17 May 2021 11:34:30 +0200
Subject: [PATCH] Don't split git references on unicode separators
---
src/pip/_internal/vcs/git.py | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/pip/_internal/vcs/git.py b/src/pip/_internal/vcs/git.py
index cc22cd7..308e857 100644
--- a/src/pip/_internal/vcs/git.py
+++ b/src/pip/_internal/vcs/git.py
@@ -147,9 +147,15 @@ class Git(VersionControl):
on_returncode='ignore',
)
refs = {}
- for line in output.strip().splitlines():
+ # NOTE: We do not use splitlines here since that would split on other
+ # unicode separators, which can be maliciously used to install a
+ # different revision.
+ for line in output.strip().split("\n"):
+ line = line.rstrip("\r")
+ if not line:
+ continue
try:
- sha, ref = line.split()
+ sha, ref = line.split(" ", maxsplit=2)
except ValueError:
# Include the offending line to simplify troubleshooting if
# this error ever occurs.
--
2.31.1

36
dummy-certifi.patch Normal file
View File

@ -0,0 +1,36 @@
From 2c58d7301dd5a47570f782fe2fce7fbb1918f60c Mon Sep 17 00:00:00 2001
From: Karolina Surma <ksurma@redhat.com>
Date: Mon, 10 May 2021 16:38:50 +0200
Subject: [PATCH] Dummy certifi patch
Co-Authored-By: Tomas Hrnciar <thrnciar@redhat.com>
---
src/pip/_vendor/certifi/core.py | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/pip/_vendor/certifi/core.py b/src/pip/_vendor/certifi/core.py
index b8140cf..f1a0b01 100644
--- a/src/pip/_vendor/certifi/core.py
+++ b/src/pip/_vendor/certifi/core.py
@@ -14,6 +14,7 @@ class _PipPatchedCertificate(Exception):
try:
+ raise ImportError # force fallback
# Return a certificate file on disk for a standalone pip zipapp running in
# an isolated build environment to use. Passing --cert to the standalone
# pip does not work since requests calls where() unconditionally on import.
@@ -67,9 +68,7 @@ except ImportError:
# If we don't have importlib.resources, then we will just do the old logic
# of assuming we're on the filesystem and munge the path directly.
def where():
- f = os.path.dirname(__file__)
-
- return os.path.join(f, "cacert.pem")
+ return '/etc/pki/tls/certs/ca-bundle.crt'
def contents():
--
2.30.2

6
gating.yaml Normal file
View File

@ -0,0 +1,6 @@
--- !Policy
product_versions:
- rhel-9
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}

16
no-version-warning.patch Normal file
View File

@ -0,0 +1,16 @@
diff --git a/src/pip/_vendor/packaging/version.py b/src/pip/_vendor/packaging/version.py
index de9a09a..154e94d 100644
--- a/src/pip/_vendor/packaging/version.py
+++ b/src/pip/_vendor/packaging/version.py
@@ -108,11 +108,6 @@ class LegacyVersion(_BaseVersion):
self._version = str(version)
self._key = _legacy_cmpkey(self._version)
- warnings.warn(
- "Creating a LegacyVersion has been deprecated and will be "
- "removed in the next major release",
- DeprecationWarning,
- )
def __str__(self) -> str:
return self._version

View File

@ -0,0 +1,74 @@
From 619782ad2d181fe2933ddf4edc7127fdc13dd0df Mon Sep 17 00:00:00 2001
From: Karolina Surma <ksurma@redhat.com>
Date: Mon, 10 May 2021 16:48:49 +0200
Subject: [PATCH] Don't warn the user about pip._internal.main() entrypoint
In Fedora, we use that in ensurepip and users cannot do anything about it,
this warning is juts moot. Also, the warning breaks CPython test suite.
Co-Authored-By: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
---
src/pip/_internal/__init__.py | 2 +-
src/pip/_internal/utils/entrypoints.py | 19 ++++++++++---------
tests/functional/test_cli.py | 3 ++-
3 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/src/pip/_internal/__init__.py b/src/pip/_internal/__init__.py
index 6afb5c6..faf25af 100755
--- a/src/pip/_internal/__init__.py
+++ b/src/pip/_internal/__init__.py
@@ -16,4 +16,4 @@ def main(args: (Optional[List[str]]) = None) -> int:
"""
from pip._internal.utils.entrypoints import _wrapper
- return _wrapper(args)
+ return _wrapper(args, _nowarn=True)
diff --git a/src/pip/_internal/utils/entrypoints.py b/src/pip/_internal/utils/entrypoints.py
index 1504a12..07d941b 100644
--- a/src/pip/_internal/utils/entrypoints.py
+++ b/src/pip/_internal/utils/entrypoints.py
@@ -4,7 +4,7 @@ from typing import List, Optional
from pip._internal.cli.main import main
-def _wrapper(args: Optional[List[str]] = None) -> int:
+def _wrapper(args: Optional[List[str]] = None, _nowarn: bool = False) -> int:
"""Central wrapper for all old entrypoints.
Historically pip has had several entrypoints defined. Because of issues
@@ -16,12 +16,13 @@ def _wrapper(args: Optional[List[str]] = None) -> int:
directing them to an appropriate place for help, we now define all of
our old entrypoints as wrappers for the current one.
"""
- sys.stderr.write(
- "WARNING: pip is being invoked by an old script wrapper. This will "
- "fail in a future version of pip.\n"
- "Please see https://github.com/pypa/pip/issues/5599 for advice on "
- "fixing the underlying issue.\n"
- "To avoid this problem you can invoke Python with '-m pip' instead of "
- "running pip directly.\n"
- )
+ if not _nowarn:
+ sys.stderr.write(
+ "WARNING: pip is being invoked by an old script wrapper. This will "
+ "fail in a future version of pip.\n"
+ "Please see https://github.com/pypa/pip/issues/5599 for advice on "
+ "fixing the underlying issue.\n"
+ "To avoid this problem you can invoke Python with '-m pip' instead of "
+ "running pip directly.\n"
+ )
return main(args)
diff --git a/tests/functional/test_cli.py b/tests/functional/test_cli.py
index e416315..7f57f67 100644
--- a/tests/functional/test_cli.py
+++ b/tests/functional/test_cli.py
@@ -31,4 +31,5 @@ def test_entrypoints_work(entrypoint, script):
result = script.pip("-V")
result2 = script.run("fake_pip", "-V", allow_stderr_warning=True)
assert result.stdout == result2.stdout
- assert "old script wrapper" in result2.stderr
+ if entrypoint[0] != "fake_pip = pip._internal:main":
+ assert "old script wrapper" in result2.stderr
--
2.32.0

View File

@ -0,0 +1,27 @@
--- /usr/bin/pip3 2019-11-12 17:37:34.793131862 +0100
+++ pip3 2019-11-12 17:40:42.014107134 +0100
@@ -2,7 +2,23 @@
# -*- coding: utf-8 -*-
import re
import sys
-from pip._internal.cli.main import main
+
+try:
+ from pip._internal.cli.main import main
+except ImportError:
+ try:
+ from pip._internal.main import main
+ except ImportError:
+ try:
+ # If the user has downgraded pip, the above import will fail.
+ # Let's try older methods of invoking it:
+
+ # pip 19 uses this
+ from pip._internal import main
+ except ImportError:
+ # older pip versions use this
+ from pip import main
+
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())

81
plan.fmf Normal file
View File

@ -0,0 +1,81 @@
execute:
how: tmt
discover:
- name: tests_python
how: shell
url: https://gitlab.com/redhat/centos-stream/tests/python.git
tests:
- name: smoke39
path: /smoke
test: VERSION=3.9 ./venv.sh
- name: smoke39_virtualenv
path: /smoke
test: VERSION=3.9 METHOD=virtualenv ./venv.sh
- name: smoke312
path: /smoke
test: VERSION=3.12 ./venv.sh
- name: smoke312_virtualenv
path: /smoke
test: VERSION=3.12 METHOD=virtualenv ./venv.sh
- name: smoke314
path: /smoke
test: VERSION=3.14 ./venv.sh
- name: smoke314_virtualenv
path: /smoke
test: VERSION=3.14 METHOD=virtualenv ./venv.sh
- name: rpms_pyproject-rpm-macros
how: shell
url: https://gitlab.com/redhat/centos-stream/rpms/pyproject-rpm-macros.git
ref: c9s
tests:
- name: pyproject_pytest
path: /tests
test: ./mocktest.sh python-pytest
- name: pyproject_entrypoints
path: /tests
test: ./mocktest.sh python-entrypoints
- name: pyproject_pluggy
path: /tests
test: ./mocktest.sh python-pluggy
- name: same_repo
how: shell
dist-git-source: true
dist-git-download-only: true
tests:
- name: pip_install_upgrade
path: /tests/pip_install_upgrade/
test: ./runtest.sh
- name: bash_completion
path: /tests/bash_completion
test: ./pip_completion_full_test.sh
prepare:
- name: Enable CRB
how: feature
crb: enabled
- name: Enable EPEL
how: feature
epel: enabled
- name: Install dependencies
how: install
package:
- gcc
- virtualenv
- python3.9-devel
- python3.12-devel
- python3.14-devel
- python3-tox
- mock
- rpmdevtools
- rpm-build
- grep
- util-linux
- shadow-utils
- expect
- dnf
- name: Update packages
how: shell
script: dnf upgrade -y

15
python-pip.rpmlintrc Normal file
View File

@ -0,0 +1,15 @@
# This is just temporary, when upstream merges PRs it can be removed
# https://github.com/ActiveState/appdirs/pull/144
# https://github.com/psf/requests/pull/5410
addFilter(r'(non-executable-script|wrong-script-interpreter) .+/pip/_vendor/appdirs.py\b')
addFilter(r'(non-executable-script|wrong-script-interpreter) .+/pip/_vendor/requests/certs.py\b')
# REQUESTED dist-info file is not meant to have any content
# Discussion: https://src.fedoraproject.org/rpms/python-pip/pull-request/69#comment-52525
addFilter(r'zero-length .+/site-packages/.+\.dist-info/REQUESTED\b')
# We ship README with the main package but not with the wheel
addFilter(r'python-pip-wheel.noarch: W: no-documentation')
# SPELLING ERRORS
addFilter(r'W: spelling-error .* venv')

843
python-pip.spec Normal file
View File

@ -0,0 +1,843 @@
# The original RHEL 9 content set is defined by (build)dependencies
# of the packages in Fedora ELN. Hence we disable tests and documentation here
# to prevent pulling many unwanted packages in.
# Once the RHEL 9 content set is defined and/or RHEL 9 forks from ELN,
# the conditional can be removed from the Fedora spec file.
# We intentionally keep this enabled on EPEL.
%if 0%{?rhel} >= 9 && !0%{?epel}
%bcond_with tests
%bcond_with doc
%else
%bcond_without tests
%bcond_without doc
%endif
%global srcname pip
%global base_version 21.3.1
%global upstream_version %{base_version}%{?prerel}
%global python_wheel_name %{srcname}-%{upstream_version}-py3-none-any.whl
%global bashcompdir %(pkg-config --variable=completionsdir bash-completion 2>/dev/null)
Name: python-%{srcname}
Version: %{base_version}%{?prerel:~%{prerel}}
Release: 2%{?dist}
Summary: A tool for installing and managing Python packages
# We bundle a lot of libraries with pip, which itself is under MIT license.
# Here is the list of the libraries with corresponding licenses:
# appdirs: MIT
# certifi: MPLv2.0
# chardet: LGPLv2
# colorama: BSD
# CacheControl: ASL 2.0
# distlib: Python
# distro: ASL 2.0
# html5lib: MIT
# idna: BSD
# ipaddress: Python
# msgpack: ASL 2.0
# packaging: ASL 2.0 or BSD
# pep517: MIT
# progress: ISC
# pyparsing: MIT
# requests: ASL 2.0
# resolvelib: ISC
# setuptools: MIT
# six: MIT
# tenacity: ASL 2.0
# tomli: MIT
# urllib3: MIT
# webencodings: BSD
License: MIT and Python and ASL 2.0 and BSD and ISC and LGPLv2 and MPLv2.0 and (ASL 2.0 or BSD)
URL: https://pip.pypa.io/
Source0: https://github.com/pypa/pip/archive/%{upstream_version}/%{srcname}-%{upstream_version}.tar.gz
BuildArch: noarch
%if %{with tests}
BuildRequires: /usr/bin/git
BuildRequires: /usr/bin/hg
BuildRequires: /usr/bin/bzr
BuildRequires: /usr/bin/svn
BuildRequires: python-setuptools-wheel
BuildRequires: python-wheel-wheel
%endif
# Prevent removing of the system packages installed under /usr/lib
# when pip install -U is executed.
# https://bugzilla.redhat.com/show_bug.cgi?id=1550368#c24
Patch3: remove-existing-dist-only-if-path-conflicts.patch
# Use the system level root certificate instead of the one bundled in certifi
# https://bugzilla.redhat.com/show_bug.cgi?id=1655253
Patch4: dummy-certifi.patch
# Don't warn the user about pip._internal.main() entrypoint
# In Fedora, we use that in ensurepip and users cannot do anything about it,
# this warning is juts moot. Also, the warning breaks CPython test suite.
Patch5: nowarn-pip._internal.main.patch
# Don't warn the user about packaging's LegacyVersion being deprecated.
# (This also breaks Python's test suite when warnings are treated as errors.)
# Upstream issue: https://github.com/pypa/packaging/issues/368
Patch6: no-version-warning.patch
# CVE-2007-4559, PEP-721, PEP-706: Use tarfile.data_filter for extracting
# - Minimal downstream-only patch, to be replaced by upstream solution
# proposed in https://github.com/pypa/pip/pull/12214
# - Test patch submitted upstream in the above pull request
# - Patch for vendored distlib, accepted upstream:
# https://github.com/pypa/distlib/pull/201
Patch7: cve-2007-4559-tarfile.patch
# Downstream only patch
# Users might have local installations of pip from using
# `pip install --user --upgrade pip` on older/newer versions.
# If they do that and they run `pip` or `pip3`, the one from /usr/bin is used.
# However that's the one from this RPM package and the import in there might
# fail (it tries to import from ~/.local, but older or newer pip is there with
# a bit different API).
# We add this patch as a dirty workaround to make /usr/bin/pip* work with
# both pip10+ (from this RPM) and older or newer (19.3+) pip (from whatever).
# A proper fix is to put ~/.local/bin in front of /usr/bin in the PATH,
# however others are against that and we cannot change it for existing
# installs/user homes anyway.
# https://bugzilla.redhat.com/show_bug.cgi?id=1569488
# https://bugzilla.redhat.com/show_bug.cgi?id=1571650
# https://bugzilla.redhat.com/show_bug.cgi?id=1767212
# WARNING: /usr/bin/pip* are entrypoints, this cannot be applied in %%prep!
# %%patch10 doesn't work outside of %%prep, so we add it as a source
# Note that since pip 20, old main() import paths are preserved for backwards
# compatibility: https://github.com/pypa/pip/issues/7498
# Meaning we don't need to update any of the older pips to support 20+
# We also don't need to update Pythons to use new import path in ensurepip
Source10: pip-allow-different-versions.patch
%description
pip is a package management system used to install and manage software packages
written in Python. Many packages can be found in the Python Package Index
(PyPI). pip is a recursive acronym that can stand for either "Pip Installs
Packages" or "Pip Installs Python".
# Virtual provides for the packages bundled by pip.
# You can generate it with:
# %%{_rpmconfigdir}/pythonbundles.py --namespace 'python%%{1}dist' src/pip/_vendor/vendor.txt
%global bundled() %{expand:
Provides: bundled(python%{1}dist(cachecontrol)) = 0.12.6
Provides: bundled(python%{1}dist(certifi)) = 2021.5.30
Provides: bundled(python%{1}dist(chardet)) = 4
Provides: bundled(python%{1}dist(colorama)) = 0.4.4
Provides: bundled(python%{1}dist(distlib)) = 0.3.3
Provides: bundled(python%{1}dist(distro)) = 1.6
Provides: bundled(python%{1}dist(html5lib)) = 1.1
Provides: bundled(python%{1}dist(idna)) = 3.2
Provides: bundled(python%{1}dist(msgpack)) = 1.0.2
Provides: bundled(python%{1}dist(packaging)) = 21
Provides: bundled(python%{1}dist(pep517)) = 0.12
Provides: bundled(python%{1}dist(platformdirs)) = 2.4
Provides: bundled(python%{1}dist(progress)) = 1.6
Provides: bundled(python%{1}dist(pyparsing)) = 2.4.7
Provides: bundled(python%{1}dist(requests)) = 2.26
Provides: bundled(python%{1}dist(resolvelib)) = 0.8
Provides: bundled(python%{1}dist(setuptools)) = 44
Provides: bundled(python%{1}dist(six)) = 1.16
Provides: bundled(python%{1}dist(tenacity)) = 8.0.1
Provides: bundled(python%{1}dist(tomli)) = 1.0.3
Provides: bundled(python%{1}dist(urllib3)) = 1.26.7
Provides: bundled(python%{1}dist(webencodings)) = 0.5.1
}
# Some manylinux1 wheels need libcrypt.so.1.
# Manylinux1, a common (as of 2019) platform tag for binary wheels, relies
# on a glibc version that included ancient crypto functions, which were
# moved to libxcrypt and then removed in:
# https://fedoraproject.org/wiki/Changes/FullyRemoveDeprecatedAndUnsafeFunctionsFromLibcrypt
# The manylinux1 standard assumed glibc would keep ABI compatibility,
# but that's only the case if libcrypt.so.1 (libxcrypt-compat) is around.
# This should be solved in the next manylinux standard (but it may be
# a long time until manylinux1 is phased out).
# See: https://github.com/pypa/manylinux/issues/305
# Note that manylinux is only applicable to x86 (both 32 and 64 bits)
%global crypt_compat_recommends() %{expand:
Recommends: (libcrypt.so.1()(64bit) if python%{1}(x86-64))
Recommends: (libcrypt.so.1 if python%{1}(x86-32))
}
%package -n python%{python3_pkgversion}-%{srcname}
Summary: A tool for installing and managing Python3 packages
BuildRequires: python%{python3_pkgversion}-devel
# python3 bootstrap: this is rebuilt before the final build of python3, which
# adds the dependency on python3-rpm-generators, so we require it manually
# Note that the package prefix is always python3-, even if we build for 3.X
# The minimal version is for bundled provides verification script
BuildRequires: python3-rpm-generators >= 11-8
BuildRequires: python%{python3_pkgversion}-setuptools
BuildRequires: bash-completion
%if %{with tests}
BuildRequires: python%{python3_pkgversion}-cryptography
BuildRequires: python%{python3_pkgversion}-mock
BuildRequires: python%{python3_pkgversion}-pytest
BuildRequires: python%{python3_pkgversion}-pretend
BuildRequires: python%{python3_pkgversion}-freezegun
BuildRequires: python%{python3_pkgversion}-scripttest
BuildRequires: python%{python3_pkgversion}-virtualenv
BuildRequires: python%{python3_pkgversion}-werkzeug
BuildRequires: python%{python3_pkgversion}-pyyaml
%endif
BuildRequires: python%{python3_pkgversion}-wheel
BuildRequires: ca-certificates
Requires: ca-certificates
# pip has to require explicit version of python3 that provides
# filters in tarfile module (fix for CVE-2007-4559).
Requires: python3 >= 3.9.17-2
# This was previously required and we keep it recommended because a lot of
# sdists installed via pip will try to import setuptools.
# But pip doesn't actually require setuptools.
# It can install wheels without them and it can build wheels in isolation mode
# (using setuptools/flit/poetry/... installed from PyPI).
# Side note: pip bundles pkg_resources from setuptools for internal usage.
Recommends: python%{python3_pkgversion}-setuptools
# Virtual provides for the packages bundled by pip:
%{bundled 3}
Provides: pip = 1:%{version}-%{release}
Conflicts: python-pip < %{version}-%{release}
%{crypt_compat_recommends 3}
# Provide platform-python-pip for backwards compatibility with RHEL 8
Provides: platform-python-pip = %{version}-%{release}
%description -n python%{python3_pkgversion}-%{srcname}
pip is a package management system used to install and manage software packages
written in Python. Many packages can be found in the Python Package Index
(PyPI). pip is a recursive acronym that can stand for either "Pip Installs
Packages" or "Pip Installs Python".
%if %{with doc}
%package doc
Summary: A documentation for a tool for installing and managing Python packages
BuildRequires: python%{python3_pkgversion}-sphinx
BuildRequires: python%{python3_pkgversion}-sphinx-inline-tabs
BuildRequires: python%{python3_pkgversion}-sphinx-copybutton
BuildRequires: python%{python3_pkgversion}-myst-parser
%description doc
A documentation for a tool for installing and managing Python packages
%endif
%package -n %{python_wheel_pkg_prefix}-%{srcname}-wheel
Summary: The pip wheel
Requires: ca-certificates
Provides: %{name}-wheel = %{version}-%{release}
Obsoletes: %{name}-wheel < %{version}-%{release}
# Older versions of python3-libs (< 3.9.9-2) expect Python wheels at the old unversioned
# location, so we conflict with the old Python versions that wouldn't work with
# the new wheel location.
# Moreover, Python older than (3.9.16-2) does not provide tarfile filters (fix for CVE-2007-4559).
Conflicts: python3-libs < 3.9.17-2
# Virtual provides for the packages bundled by pip:
%{bundled 3}
%{crypt_compat_recommends 3}
%description -n %{python_wheel_pkg_prefix}-%{srcname}-wheel
A Python wheel of pip to use with venv.
%prep
%autosetup -p1 -n %{srcname}-%{upstream_version}
# this goes together with patch4
rm src/pip/_vendor/certifi/*.pem
# Do not use furo as HTML theme in docs
# furo is not available in Fedora
sed -i '/html_theme = "furo"/d' docs/html/conf.py
# towncrier extension for Sphinx is not yet available in Fedora
sed -i '/"sphinxcontrib.towncrier",/d' docs/html/conf.py
# tests expect wheels in here
ln -s %{python_wheel_dir} tests/data/common_wheels
# Remove shebang from files in bundled chardet
grep -lr "^#\!/usr/bin/env python" src/pip/_vendor/chardet/ | xargs sed -i "1d"
# Remove windows executable binaries
rm -v src/pip/_vendor/distlib/*.exe
sed -i '/\.exe/d' setup.py
%build
%py3_build_wheel
%if %{with doc}
export PYTHONPATH=./src/
# from tox.ini
sphinx-build-3 -b html docs/html docs/build/html
sphinx-build-3 -b man docs/man docs/build/man -c docs/html
rm -rf docs/build/html/{.doctrees,.buildinfo}
%endif
%install
# The following is similar to %%pyproject_install, but we don't have
# /usr/bin/pip yet, so we install using the wheel directly.
# (This is not standard wheel usage, but the pip wheel supports it -- see
# pip/__main__.py)
%{python3} dist/%{python_wheel_name}/pip install \
--root %{buildroot} \
--no-deps \
--disable-pip-version-check \
--progress-bar off \
--verbose \
--ignore-installed \
--no-warn-script-location \
--no-index \
--no-cache-dir \
--find-links dist \
'pip==%{upstream_version}'
%if %{with doc}
pushd docs/build/man
install -d %{buildroot}%{_mandir}/man1
for MAN in *1; do
install -pm0644 $MAN %{buildroot}%{_mandir}/man1/$MAN
for pip in "pip3" "pip-3" "pip%{python3_version}" "pip-%{python3_version}"; do
echo ".so $MAN" > %{buildroot}%{_mandir}/man1/${MAN/pip/$pip}
done
done
popd
%endif
# before we ln -s anything, we apply Source10 patch to all pips:
for PIP in %{buildroot}%{_bindir}/pip*; do
patch -p1 --no-backup-if-mismatch $PIP < %{SOURCE10}
done
mkdir -p %{buildroot}%{bashcompdir}
PYTHONPATH=%{buildroot}%{python3_sitelib} \
%{buildroot}%{_bindir}/pip completion --bash \
> %{buildroot}%{bashcompdir}/pip3
# Make bash completion apply to all the 5 symlinks we install
sed -i -e "s/^\\(complete.*\\) pip\$/\\1 pip pip{,-}{3,%{python3_version}}/" \
-e s/_pip_completion/_pip3_completion/ \
%{buildroot}%{bashcompdir}/pip3
# Provide symlinks to executables to comply with Fedora guidelines for Python
ln -s ./pip%{python3_version} %{buildroot}%{_bindir}/pip-%{python3_version}
ln -s ./pip-%{python3_version} %{buildroot}%{_bindir}/pip-3
# Make sure the INSTALLER is not pip and remove RECORD
# %%pyproject macros do this for all packages
echo rpm > %{buildroot}%{python3_sitelib}/pip-%{upstream_version}.dist-info/INSTALLER
rm %{buildroot}%{python3_sitelib}/pip-%{upstream_version}.dist-info/RECORD
mkdir -p %{buildroot}%{python_wheel_dir}
install -p dist/%{python_wheel_name} -t %{buildroot}%{python_wheel_dir}
%if %{with tests}
%check
# Verify bundled provides are up to date
%{_rpmconfigdir}/pythonbundles.py src/pip/_vendor/vendor.txt --compare-with '%{bundled 3}'
# Upstream tests
# bash completion tests only work from installed package
# needs unaltered sys.path and we cannot do that in %%check
# test_pep517_and_build_options
# test_config_file_venv_option
# Incompatible with the latest virtualenv
# test_from_link_vcs_with_source_dir_obtains_commit_id
# test_from_link_vcs_without_source_dir
# test_should_cache_git_sha
pytest_k='not completion and
not test_pep517_and_build_options and
not test_config_file_venv_option and
not test_from_link_vcs_with_source_dir_obtains_commit_id and
not test_from_link_vcs_without_source_dir and
not test_should_cache_git_sha'
# test_pep517 and test_pep660 are ignored entirely, as they import tomli_w and we don't have that packaged yet
# --deselect'ed tests are not compatible with the latest virtualenv
# These files contain almost 500 tests so we should enable them back
# as soon as pip will be compatible upstream
# https://github.com/pypa/pip/pull/8441
%pytest -m 'not network' -k "$(echo $pytest_k)" \
--ignore tests/functional/test_pep660.py --ignore tests/functional/test_pep517.py \
--deselect tests/functional --deselect tests/lib/test_lib.py --deselect tests/unit/test_build_env.py
%endif
%files -n python%{python3_pkgversion}-%{srcname}
%doc README.rst
%license %{python3_sitelib}/pip-%{upstream_version}.dist-info/LICENSE.txt
%if %{with doc}
%{_mandir}/man1/pip.*
%{_mandir}/man1/pip-*.*
%{_mandir}/man1/pip3.*
%{_mandir}/man1/pip3-*.*
%endif
%{_bindir}/pip
%{_bindir}/pip3
%{_bindir}/pip-3
%{_bindir}/pip%{python3_version}
%{_bindir}/pip-%{python3_version}
%{python3_sitelib}/pip*
%dir %{bashcompdir}
%{bashcompdir}/pip3
%if %{with doc}
%files doc
%license LICENSE.txt
%doc README.rst
%doc docs/build/html
%endif
%files -n %{python_wheel_pkg_prefix}-%{srcname}-wheel
%license LICENSE.txt
# we own the dir for simplicity
%dir %{python_wheel_dir}/
%{python_wheel_dir}/%{python_wheel_name}
%changelog
* Tue May 19 2026 Miro Hrončok <mhroncok@redhat.com> - 21.3.1-2
- Bump epoch for the virtual pip Provide, for this package to take precedence over python3.14-pip
Resolves: RHEL-178095
* Tue Mar 19 2024 Lumír Balhar <lbalhar@redhat.com> - 21.3.1-1
- Update to 21.3.1
Resolves: RHEL-29310
* Wed Feb 14 2024 Lumír Balhar <lbalhar@redhat.com> - 21.2.3-8
- Require Python with tarfile filters
Resolves: RHEL-25451
* Tue Aug 08 2023 Petr Viktorin <pviktori@redhat.com> - 21.2.3-7
- Use tarfile.data_filter for extracting (CVE-2007-4559, PEP-721, PEP-706)
Resolves: RHBZ#2207997
* Thu Feb 03 2022 Tomas Orsava <torsava@redhat.com> - 21.2.3-6
- Add automatically generated Obsoletes tag with the python39- prefix
for smoother upgrade from RHEL8
- Related: rhbz#1990421
* Wed Nov 24 2021 Tomas Orsava <torsava@redhat.com> - 21.2.3-5
- Conflict with old Python versions that use the old unversioned wheel location
- Resolves: rhbz#1982668
* Fri Nov 5 2021 Tomas Orsava <torsava@redhat.com> - 21.2.3-4
- Make the python-pip-wheel subpackage versioned (python3-pip-wheel),
and move its contents to a versioned directory /usr/share/python3-wheels
- Resolves: rhbz#1982668
* Wed Oct 06 2021 Charalampos Stratakis <cstratak@redhat.com> - 21.2.3-3
- Remove bundled windows executables
- Resolves: rhbz#2006795
* Mon Sep 13 2021 Miro Hrončok <mhroncok@redhat.com> - 21.2.3-2
- Fix broken uninstallation by a bogus downstream patch
* Mon Sep 13 2021 Miro Hrončok <mhroncok@redhat.com> - 21.2.3-1
- Update to 21.2.3
- Resolves: rhbz#1985635
* Mon Sep 13 2021 Lumír Balhar <lbalhar@redhat.com> - 21.1.3-1
- Update to 21.1.3
Resolves: rhbz#1976449
* Mon Sep 13 2021 Karolina Surma <ksurma@redhat.com> - 21.1.2-1
- Update to 21.1.2
Resolves: rhbz#1963433
* Mon Sep 13 2021 Karolina Surma <ksurma@redhat.com> - 21.1.1-1
- Update to 21.1.1
* Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com> - 21.0.1-6
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Wed Jul 28 2021 Tomas Orsava <torsava@redhat.com> - 21.0.1-5
- Provide the platform-python-pip name for backwards compatibility
with RHEL 8
- Related: rhbz#1891487
* Mon May 17 2021 Karolina Surma <ksurma@redhat.com> - 21.0.1-4
- Backport security fixes from pip 21.1.1
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com>
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Sat Mar 13 2021 Miro Hrončok <mhroncok@redhat.com> - 21.0.1-2
- python-pip-wheel: Remove bundled provides and libcrypt recommends for Python 2
(The wheel is Python 3 only for a while)
* Wed Feb 17 2021 Lumír Balhar <lbalhar@redhat.com> - 21.0.1-1
- Update to 21.0.1
Resolves: rhbz#1922592
* Tue Jan 26 2021 Lumír Balhar <lbalhar@redhat.com> - 21.0-1
- Update to 21.0 (#1919530)
* Thu Dec 17 2020 Petr Viktorin <pviktori@redhat.com> - 20.3.3-1
- Update to 20.3.3
* Mon Nov 30 2020 Miro Hrončok <mhroncok@redhat.com> - 20.3-1
- Update to 20.3
- Add support for PEP 600: Future manylinux Platform Tags
- New resolver
- Fixes: rhbz#1893470
* Mon Oct 19 2020 Lumír Balhar <lbalhar@redhat.com> - 20.2.4-1
- Update to 20.2.4 (#1889112)
* Wed Aug 05 2020 Tomas Orsava <torsava@redhat.com> - 20.2.2-1
- Update to 20.2.2 (#1838553)
* Wed Jul 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 20.1.1-7
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Fri Jul 10 2020 Lumír Balhar <lbalhar@redhat.com> - 20.1.1-6
- Do not emit a warning about root privileges when --root is used
* Wed Jul 08 2020 Miro Hrončok <mhroncok@redhat.com> - 20.1.1-5
- Update bundled provides to match 20.1.1
* Tue Jun 16 2020 Lumír Balhar <lbalhar@redhat.com> - 20.1.1-4
- Deselect tests incompatible with the latest virtualenv
* Sun May 24 2020 Miro Hrončok <mhroncok@redhat.com> - 20.1.1-3
- Rebuilt for Python 3.9
* Thu May 21 2020 Miro Hrončok <mhroncok@redhat.com> - 20.1.1-2
- Bootstrap for Python 3.9
* Wed May 20 2020 Tomas Hrnciar <thrnciar@redhat.com> - 20.1.1-1
- Update to 20.1.1
* Wed Apr 29 2020 Tomas Hrnciar <thrnciar@redhat.com> - 20.1-1
- Update to 20.1
* Mon Apr 27 2020 Tomas Hrnciar <thrnciar@redhat.com> - 20.1~b1-1
- Update to 20.1~b1
* Wed Apr 15 2020 Miro Hrončok <mhroncok@redhat.com> - 20.0.2-4
- Only recommend setuptools, don't require them
* Fri Apr 10 2020 Miro Hrončok <mhroncok@redhat.com> - 20.0.2-3
- Allow setting $TMPDIR to $PWD/... during pip wheel (#1806625)
* Tue Mar 10 2020 Miro Hrončok <mhroncok@redhat.com> - 20.0.2-2
- Don't warn the user about pip._internal.main() entrypoint to fix ensurepip
* Mon Mar 02 2020 Miro Hrončok <mhroncok@redhat.com> - 20.0.2-1
- Update to 20.0.2 (#1793456)
* Thu Jan 30 2020 Fedora Release Engineering <releng@fedoraproject.org> - 19.3.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Mon Nov 04 2019 Tomas Orsava <torsava@redhat.com> - 19.3.1-1
- Update to 19.3.1 (#1761508)
- Drop upstreamed patch that fixed expected output in test to not break with alpha/beta/rc Python versions
* Wed Oct 30 2019 Miro Hrončok <mhroncok@redhat.com> - 19.2.3-2
- Make /usr/bin/pip(3) work with user-installed pip 19.3+ (#1767212)
* Mon Sep 02 2019 Miro Hrončok <mhroncok@redhat.com> - 19.2.3-1
- Update to 19.2.3 (#1742230)
- Drop patch that should strip path prefixes from RECORD files, the paths are relative
* Wed Aug 21 2019 Petr Viktorin <pviktori@redhat.com> - 19.1.1-8
- Remove python2-pip
- Make pip bootstrap itself, rather than with an extra bootstrap RPM build
* Sat Aug 17 2019 Miro Hrončok <mhroncok@redhat.com> - 19.1.1-7
- Rebuilt for Python 3.8
* Wed Aug 14 2019 Miro Hrončok <mhroncok@redhat.com> - 19.1.1-6
- Bootstrap for Python 3.8
* Wed Aug 14 2019 Miro Hrončok <mhroncok@redhat.com> - 19.1.1-5
- Bootstrap for Python 3.8
* Fri Jul 26 2019 Fedora Release Engineering <releng@fedoraproject.org> - 19.1.1-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Mon Jul 15 2019 Petr Viktorin <pviktori@redhat.com> - 19.1.1-3
- Recommend libcrypt.so.1 for manylinux1 compatibility
- Make /usr/bin/pip Python 3
* Mon Jun 10 2019 Miro Hrončok <mhroncok@redhat.com> - 19.1.1-2
- Fix root warning when pip is invoked via python -m pip
- Remove a redundant second WARNING prefix form the abovementioned warning
* Wed May 15 2019 Miro Hrončok <mhroncok@redhat.com> - 19.1.1-1
- Update to 19.1.1 (#1706995)
* Thu Apr 25 2019 Miro Hrončok <mhroncok@redhat.com> - 19.1-1
- Update to 19.1 (#1702525)
* Wed Mar 06 2019 Miro Hrončok <mhroncok@redhat.com> - 19.0.3-1
- Update to 19.0.3 (#1679277)
* Wed Feb 13 2019 Miro Hrončok <mhroncok@redhat.com> - 19.0.2-1
- Update to 19.0.2 (#1668492)
* Sat Feb 02 2019 Fedora Release Engineering <releng@fedoraproject.org> - 18.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Mon Dec 03 2018 Miro Hrončok <mhroncok@redhat.com> - 18.1-2
- Use the system level root certificate instead of the one bundled in certifi
* Thu Nov 22 2018 Miro Hrončok <mhroncok@redhat.com> - 18.1-1
- Update to 18.1 (#1652089)
* Tue Sep 18 2018 Victor Stinner <vstinner@redhat.com> - 18.0-4
- Prevent removing of the system packages installed under /usr/lib
when pip install -U is executed. Original patch by Michal Cyprian.
Resolves: rhbz#1550368.
* Wed Aug 08 2018 Miro Hrončok <mhroncok@redhat.com> - 18.0-3
- Create python-pip-wheel package with the wheel
* Tue Jul 31 2018 Miro Hrončok <mhroncok@redhat.com> - 18.0-2
- Remove redundant "Unicode" from License
* Mon Jul 23 2018 Marcel Plch <mplch@redhat.com> - 18.0-7
- Update to 18.0
* Sat Jul 14 2018 Fedora Release Engineering <releng@fedoraproject.org> - 9.0.3-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Mon Jun 18 2018 Miro Hrončok <mhroncok@redhat.com> - 9.0.3-5
- Rebuilt for Python 3.7
* Wed Jun 13 2018 Miro Hrončok <mhroncok@redhat.com> - 9.0.3-4
- Bootstrap for Python 3.7
* Wed Jun 13 2018 Miro Hrončok <mhroncok@redhat.com> - 9.0.3-3
- Bootstrap for Python 3.7
* Fri May 04 2018 Miro Hrončok <mhroncok@redhat.com> - 9.0.3-2
- Allow to import pip10's main from pip9's /usr/bin/pip
- Do not show the "new version of pip" warning outside of venv
Resolves: rhbz#1569488
Resolves: rhbz#1571650
Resolves: rhbz#1573755
* Thu Mar 29 2018 Charalampos Stratakis <cstratak@redhat.com> - 9.0.3-1
- Update to 9.0.3
* Wed Feb 21 2018 Lumír Balhar <lbalhar@redhat.com> - 9.0.1-16
- Include built HTML documentation (in the new -doc subpackage) and man page
* Fri Feb 09 2018 Fedora Release Engineering <releng@fedoraproject.org> - 9.0.1-15
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
* Mon Dec 04 2017 Charalampos Stratakis <cstratak@redhat.com> - 9.0.1-14
- Reintroduce the ipaddress module in the python3 subpackage.
* Mon Nov 20 2017 Charalampos Stratakis <cstratak@redhat.com> - 9.0.1-13
- Add virtual provides for the bundled libraries. (rhbz#1096912)
* Tue Aug 29 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-12
- Switch macros to bcond's and make Python 2 optional to facilitate building
the Python 2 and Python 3 modules
* Thu Jul 27 2017 Fedora Release Engineering <releng@fedoraproject.org> - 9.0.1-11
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
* Tue May 23 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-10
- Modernized package descriptions
Resolves: rhbz#1452568
* Tue Mar 21 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-9
- Fix typo in the sudo pip warning
* Fri Mar 03 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-8
- Patch 1 update: No sudo pip warning in venv or virtualenv
* Thu Feb 23 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-7
- Patch 1 update: Customize the warning with the proper version of the pip
command
* Tue Feb 14 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-6
- Added patch 1: Emit a warning when running with root privileges
* Sat Feb 11 2017 Fedora Release Engineering <releng@fedoraproject.org> - 9.0.1-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
* Mon Jan 02 2017 Tomas Orsava <torsava@redhat.com> - 9.0.1-4
- Provide symlinks to executables to comply with Fedora guidelines for Python
Resolves: rhbz#1406922
* Fri Dec 09 2016 Charalampos Stratakis <cstratak@redhat.com> - 9.0.1-3
- Rebuild for Python 3.6 with wheel
* Fri Dec 09 2016 Charalampos Stratakis <cstratak@redhat.com> - 9.0.1-2
- Rebuild for Python 3.6 without wheel
* Fri Nov 18 2016 Orion Poplawski <orion@cora.nwra.com> - 9.0.1-1
- Update to 9.0.1
* Fri Nov 18 2016 Orion Poplawski <orion@cora.nwra.com> - 8.1.2-5
- Enable EPEL Python 3 builds
- Use new python macros
- Cleanup spec
* Fri Aug 05 2016 Tomas Orsava <torsava@redhat.com> - 8.1.2-4
- Updated the test sources
* Fri Aug 05 2016 Tomas Orsava <torsava@redhat.com> - 8.1.2-3
- Moved python-pip into the python2-pip subpackage
- Added the python_provide macro
* Tue Jul 19 2016 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 8.1.2-2
- https://fedoraproject.org/wiki/Changes/Automatic_Provides_for_Python_RPM_Packages
* Tue May 17 2016 Tomas Orsava <torsava@redhat.com> - 8.1.2-1
- Update to 8.1.2
- Moved to a new PyPI URL format
- Updated the prefix-stripping patch because of upstream changes in pip/wheel.py
* Mon Feb 22 2016 Slavek Kabrda <bkabrda@redhat.com> - 8.0.2-1
- Update to 8.0.2
* Thu Feb 04 2016 Fedora Release Engineering <releng@fedoraproject.org> - 7.1.0-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
* Wed Oct 14 2015 Robert Kuska <rkuska@redhat.com> - 7.1.0-3
- Rebuilt for Python3.5 rebuild
- With wheel set to 1
* Tue Oct 13 2015 Robert Kuska <rkuska@redhat.com> - 7.1.0-2
- Rebuilt for Python3.5 rebuild
* Wed Jul 01 2015 Slavek Kabrda <bkabrda@redhat.com> - 7.1.0-1
- Update to 7.1.0
* Tue Jun 30 2015 Ville Skyttä <ville.skytta@iki.fi> - 7.0.3-3
- Install bash completion
- Ship LICENSE.txt as %%license where available
* Thu Jun 18 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 7.0.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
* Thu Jun 04 2015 Matej Stuchlik <mstuchli@redhat.com> - 7.0.3-1
- Update to 7.0.3
* Fri Mar 06 2015 Matej Stuchlik <mstuchli@redhat.com> - 6.0.8-1
- Update to 6.0.8
* Thu Dec 18 2014 Slavek Kabrda <bkabrda@redhat.com> - 1.5.6-5
- Only enable tests on Fedora.
* Mon Dec 01 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.6-4
- Add tests
- Add patch skipping tests requiring Internet access
* Tue Nov 18 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.6-3
- Added patch for local dos with predictable temp dictionary names
(http://seclists.org/oss-sec/2014/q4/655)
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.5.6-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
* Sun May 25 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.6-1
- Update to 1.5.6
* Fri Apr 25 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.4-4
- Rebuild as wheel for Python 3.4
* Thu Apr 24 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.4-3
- Disable build_wheel
* Thu Apr 24 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.4-2
- Rebuild as wheel for Python 3.4
* Mon Apr 07 2014 Matej Stuchlik <mstuchli@redhat.com> - 1.5.4-1
- Updated to 1.5.4
* Mon Oct 14 2013 Tim Flink <tflink@fedoraproject.org> - 1.4.1-1
- Removed patch for CVE 2013-2099 as it has been included in the upstream 1.4.1 release
- Updated version to 1.4.1
* Sun Aug 04 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.3.1-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
* Tue Jul 16 2013 Toshio Kuratomi <toshio@fedoraproject.org> - 1.3.1-4
- Fix for CVE 2013-2099
* Thu May 23 2013 Tim Flink <tflink@fedoraproject.org> - 1.3.1-3
- undo python2 executable rename to python-pip. fixes #958377
- fix summary to match upstream
* Mon May 06 2013 Kevin Kofler <Kevin@tigcc.ticalc.org> - 1.3.1-2
- Fix main package Summary, it's for Python 2, not 3 (#877401)
* Fri Apr 26 2013 Jon Ciesla <limburgher@gmail.com> - 1.3.1-1
- Update to 1.3.1, fix for CVE-2013-1888.
* Thu Feb 14 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.2.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
* Tue Oct 09 2012 Tim Flink <tflink@fedoraproject.org> - 1.2.1-2
- Fixing files for python3-pip
* Thu Oct 04 2012 Tim Flink <tflink@fedoraproject.org> - 1.2.1-1
- Update to upstream 1.2.1
- Change binary from pip-python to python-pip (RHBZ#855495)
- Add alias from python-pip to pip-python, to be removed at a later date
* Tue May 15 2012 Tim Flink <tflink@fedoraproject.org> - 1.1.0-1
- Update to upstream 1.1.0
* Sat Jan 14 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.0.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
* Sat Oct 22 2011 Tim Flink <tflink@fedoraproject.org> - 1.0.2-1
- update to 1.0.2 and added python3 subpackage
* Wed Jun 22 2011 Tim Flink <tflink@fedoraproject.org> - 0.8.3-1
- update to 0.8.3 and project home page
* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.8.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
* Mon Dec 20 2010 Luke Macken <lmacken@redhat.com> - 0.8.2-1
- update to 0.8.2 of pip
* Mon Aug 30 2010 Peter Halliday <phalliday@excelsiorsystems.net> - 0.8-1
- update to 0.8 of pip
* Thu Jul 22 2010 David Malcolm <dmalcolm@redhat.com> - 0.7.2-5
- Rebuilt for https://fedoraproject.org/wiki/Features/Python_2.7/MassRebuild
* Wed Jul 7 2010 Peter Halliday <phalliday@excelsiorsystems.net> - 0.7.2-1
- update to 0.7.2 of pip
* Sun May 23 2010 Peter Halliday <phalliday@excelsiorsystems.net> - 0.7.1-1
- update to 0.7.1 of pip
* Fri Jan 1 2010 Peter Halliday <phalliday@excelsiorsystems.net> - 0.6.1.4
- fix dependency issue
* Fri Dec 18 2009 Peter Halliday <phalliday@excelsiorsystems.net> - 0.6.1-2
- fix spec file
* Thu Dec 17 2009 Peter Halliday <phalliday@excelsiorsystems.net> - 0.6.1-1
- upgrade to 0.6.1 of pip
* Mon Aug 31 2009 Peter Halliday <phalliday@excelsiorsystems.net> - 0.4-1
- Initial package

View File

@ -0,0 +1,141 @@
From f5c7cdc676e6884580fde4689a296ff50a9847a5 Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Wed, 20 Mar 2024 13:43:12 +0100
Subject: [PATCH] Prevent removing of the system packages installed under
/usr/lib when pip install -U is executed.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Resolves: rhbz#1550368
Co-Authored-By: Michal Cyprian <m.cyprian@gmail.com>
Co-Authored-By: Victor Stinner <vstinner@redhat.com>
Co-Authored-By: Petr Viktorin <pviktori@redhat.com>
Co-Authored-By: Lumir Balhar <lbalhar@redhat.com>
Co-Authored-By: Miro Hrončok <miro@hroncok.cz>
---
src/pip/_internal/req/req_install.py | 3 ++-
src/pip/_internal/resolution/legacy/resolver.py | 5 ++++-
src/pip/_internal/resolution/resolvelib/factory.py | 10 ++++++++++
src/pip/_internal/utils/misc.py | 11 +++++++++++
4 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/src/pip/_internal/req/req_install.py b/src/pip/_internal/req/req_install.py
index 95dacab..b9679fa 100644
--- a/src/pip/_internal/req/req_install.py
+++ b/src/pip/_internal/req/req_install.py
@@ -47,6 +47,7 @@ from pip._internal.utils.misc import (
ask_path_exists,
backup_dir,
display_path,
+ dist_in_install_path,
dist_in_site_packages,
dist_in_usersite,
get_distribution,
@@ -442,7 +443,7 @@ class InstallRequirement:
existing_dist.project_name, existing_dist.location
)
)
- else:
+ elif dist_in_install_path(existing_dist):
self.should_reinstall = True
else:
if self.editable:
diff --git a/src/pip/_internal/resolution/legacy/resolver.py b/src/pip/_internal/resolution/legacy/resolver.py
index 09caaa6..c1542ec 100644
--- a/src/pip/_internal/resolution/legacy/resolver.py
+++ b/src/pip/_internal/resolution/legacy/resolver.py
@@ -44,6 +44,7 @@ from pip._internal.resolution.base import BaseResolver, InstallRequirementProvid
from pip._internal.utils.compatibility_tags import get_supported
from pip._internal.utils.logging import indent_log
from pip._internal.utils.misc import dist_in_usersite, normalize_version_info
+from pip._internal.utils.misc import dist_in_install_path
from pip._internal.utils.packaging import check_requires_python
logger = logging.getLogger(__name__)
@@ -203,7 +204,9 @@ class Resolver(BaseResolver):
"""
# Don't uninstall the conflict if doing a user install and the
# conflict is not a user install.
- if not self.use_user_site or dist_in_usersite(req.satisfied_by):
+ if ((not self.use_user_site
+ or dist_in_usersite(req.satisfied_by))
+ and dist_in_install_path(req.satisfied_by)):
req.should_reinstall = True
req.satisfied_by = None
diff --git a/src/pip/_internal/resolution/resolvelib/factory.py b/src/pip/_internal/resolution/resolvelib/factory.py
index 766dc26..baf61ba 100644
--- a/src/pip/_internal/resolution/resolvelib/factory.py
+++ b/src/pip/_internal/resolution/resolvelib/factory.py
@@ -1,6 +1,7 @@
import contextlib
import functools
import logging
+import sys
from typing import (
TYPE_CHECKING,
Dict,
@@ -33,6 +34,7 @@ from pip._internal.exceptions import (
UnsupportedWheel,
)
from pip._internal.index.package_finder import PackageFinder
+from pip._internal.locations import get_scheme
from pip._internal.metadata import BaseDistribution, get_default_environment
from pip._internal.models.link import Link
from pip._internal.models.wheel import Wheel
@@ -45,6 +47,7 @@ from pip._internal.req.req_install import (
from pip._internal.resolution.base import InstallRequirementProvider
from pip._internal.utils.compatibility_tags import get_supported
from pip._internal.utils.hashes import Hashes
+from pip._internal.utils.misc import dist_location
from pip._internal.utils.packaging import get_requirement
from pip._internal.utils.virtualenv import running_under_virtualenv
@@ -526,6 +529,13 @@ class Factory:
if dist is None: # Not installed, no uninstallation required.
return None
+ # Prevent uninstalling packages from /usr
+ if dist_location(dist._dist) in (
+ get_scheme('', prefix=sys.base_prefix).purelib,
+ get_scheme('', prefix=sys.base_prefix).platlib,
+ ):
+ return None
+
# We're installing into global site. The current installation must
# be uninstalled, no matter it's in global or user site, because the
# user site installation has precedence over global.
diff --git a/src/pip/_internal/utils/misc.py b/src/pip/_internal/utils/misc.py
index d3e9053..d25d1c3 100644
--- a/src/pip/_internal/utils/misc.py
+++ b/src/pip/_internal/utils/misc.py
@@ -38,6 +38,7 @@ from pip._vendor.tenacity import retry, stop_after_delay, wait_fixed
from pip import __version__
from pip._internal.exceptions import CommandError
from pip._internal.locations import get_major_minor_version, site_packages, user_site
+from pip._internal.locations import get_scheme
from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.egg_link import egg_link_path_from_location
from pip._internal.utils.virtualenv import running_under_virtualenv
@@ -354,6 +355,16 @@ def dist_in_site_packages(dist: Distribution) -> bool:
return dist_location(dist).startswith(normalize_path(site_packages))
+def dist_in_install_path(dist):
+ """
+ Return True if given Distribution is installed in
+ path matching distutils_scheme layout.
+ """
+ norm_path = normalize_path(dist_location(dist))
+ return norm_path.startswith(normalize_path(
+ get_scheme("").purelib.split('python')[0]))
+
+
def get_distribution(req_name: str) -> Optional[Distribution]:
"""Given a requirement name, return the installed Distribution object.
--
2.44.0

5
rpminspect.yaml Normal file
View File

@ -0,0 +1,5 @@
# completely disabled inspections:
inspections:
# we know about RIGHT-TO-LEFT OVERRIDE in AUTHORS.txt
# (fine tuning of this inspection does not seem to work)
unicode: off

1
sources Normal file
View File

@ -0,0 +1 @@
SHA512 (pip-21.3.1.tar.gz) = 2f50f95fe36cffc18821a70824f5b28d03598894f9ea5b02acc4921d16fc7739131814828a2159bcd577331cc780c7776a3669fa1ca2d4690c861add10a16f00

View File

@ -0,0 +1,35 @@
summary: PIP bash completion functionality smoke test
description: |
Comprehensive test for pip bash completion functionality on Fedora/RHEL systems.
The test performs the following steps:
1. Finds the bash completion script in the given (e.g. python3-pip) RPM package
2. Discovers all pip executables in the package (e.g. /usr/bin/pip and /usr/bin/pip3.14)
3. Sources the completion script and verifies completion for all executables is registered
4. Runs functional TAB completion tests using expect (for regular and POSIX mode of Bash)
5. Validates that completion works for basic pip commands
This is a smoke test to ensure pip bash completion is properly
installed and functional after package installation.
component:
- python3-pip
test: ./pip_completion_full_test.sh
framework: shell
duration: 5m
tier: 1
require:
- python3-pip
- bash-completion
- expect
- rpm
- bash
environment:
PACKAGE: python3-pip

View File

@ -0,0 +1,88 @@
#!/bin/bash
# Comprehensive PIP bash completion test for RHEL
# Finds completion scripts from RPM, tests all pip binaries, and runs functional tests
PACKAGE="${PACKAGE:-python3-pip}"
# Step 1: Find bash completion scripts in python3-pip RPM package
echo "Step 1: Finding bash completion scripts in $PACKAGE RPM package..."
COMPLETION_FILE=$(rpm -ql $PACKAGE 2>/dev/null | grep -E "/usr/share/bash-completion/completions/" || true)
if [[ -z "$COMPLETION_FILE" ]]; then
echo "✗ No bash completion files found in $PACKAGE package"
exit 1
fi
# Check if there's exactly one completion file
COMPLETION_FILE_COUNT=$(echo "$COMPLETION_FILE" | wc -l)
if [[ $COMPLETION_FILE_COUNT -gt 1 ]]; then
echo "✗ Multiple bash completion files found in $PACKAGE package:"
echo "$COMPLETION_FILE" | sed 's/^/ - /'
echo "Expected exactly one completion file, found $COMPLETION_FILE_COUNT"
exit 1
fi
echo "✓ Found completion file from $PACKAGE package:"
echo "$COMPLETION_FILE" | sed 's/^/ - /'
# Step 2: Find all pip binaries
echo
echo "Step 2: Finding all pip binaries..."
PIP_BINARIES=()
PIP_FILES=$(rpm -ql $PACKAGE | grep /bin/p)
for pip_file in $PIP_FILES; do
if [[ -x "$pip_file" ]]; then
pip_cmd=$(basename "$pip_file")
PIP_BINARIES+=("$pip_cmd")
echo "✓ Found: $pip_cmd -> $pip_file"
fi
done
if [[ ${#PIP_BINARIES[@]} -eq 0 ]]; then
echo "✗ No pip binaries found"
exit 1
fi
echo "Total pip binaries found: ${#PIP_BINARIES[@]}"
# Step 3: Source completion scripts and test each binary
echo
echo "Step 3: Testing completion for each pip binary..."
for AS_POSIX in 0 1; do
if [[ $AS_POSIX -eq 1 ]]; then
echo "Testing in POSIX mode"
POSIX="--posix"
else
echo "Testing in non-POSIX mode"
POSIX=""
fi
echo "Sourcing: $COMPLETION_FILE"
if bash --norc $POSIX -c "source $COMPLETION_FILE" ; then
echo "✓ Successfully sourced $COMPLETION_FILE"
else
echo "! Warning: Failed to source $COMPLETION_FILE"
exit 1
fi
export AS_POSIX
for pip_exec in "${PIP_BINARIES[@]}"; do
echo "Running expect test with $COMPLETION_FILE and $pip_exec..."
if ./test_pip_completion.exp "$COMPLETION_FILE" "$pip_exec"; then
echo "✓ Functional test passed"
else
echo "✗ Functional test failed"
exit 1
fi
done
done
echo "✓ All tests completed successfully!"

View File

@ -0,0 +1,117 @@
#!/usr/bin/expect -f
# PIP bash completion smoke test using expect
# Tests actual TAB completion functionality
# Usage: test_pip_completion.exp [completion_file] [pip_binary]
set timeout 5
set completion_file [lindex $argv 0]
set pip_exec [lindex $argv 1]
puts "=== PIP Bash Completion Test (using expect) ==="
puts "Testing completion file: $completion_file"
puts "Testing pip binary: $pip_exec"
# Check if completion file exists first
if {![file exists $completion_file]} {
puts "✗ Completion file not found: $completion_file"
exit 1
}
puts "✓ Completion file found: $completion_file"
# Start bash shell
if {[info exists env(AS_POSIX)] && $env(AS_POSIX) == "1"} {
spawn bash --norc --posix
} else {
spawn bash --norc
}
expect "$ "
# Source the completion file
send "source $completion_file\r"
expect "$ "
puts "Attempted to source completion file"
# Test 1: Basic pip command completion
puts "\nTest 1: Testing '$pip_exec ' + TAB completion..."
send "$pip_exec "
sleep 0.1
# Send TAB TAB using hex codes
send "\x09\x09"
expect {
-re "(install|uninstall|list|show)" {
puts "✓ Basic pip commands found in completion"
expect "$ "
}
-re "Display all" {
puts "✓ Completion showing options menu"
send "n\r"
expect "$ "
}
timeout {
puts "✗ Timeout waiting for completion - test failed"
exit 1
}
}
# Clear the line and ensure clean prompt
send "\x03"
expect "$ "
send "\r"
expect "$ "
# Test 2: Test partial command completion (simpler test)
puts "\nTest 2: Testing '$pip_exec insta' + TAB completion..."
send "$pip_exec insta"
sleep 0.1
# Single TAB for completion
send "\x09"
expect {
-re "install" {
puts "✓ Partial command completion works (insta -> install)"
expect "$ "
}
timeout {
puts "✗ Timeout on partial completion test - test failed"
exit 1
}
}
# Clear the line and ensure clean prompt
send "\x03"
expect "$ "
send "\r"
expect "$ "
# Test 3: Test help completion
puts "\nTest 3: Testing '$pip_exec --' + TAB completion..."
send "$pip_exec --"
sleep 0.1
send "\x09\x09"
expect {
-re "(--help|--version)" {
puts "✓ Command options found in completion"
expect "$ "
}
timeout {
puts "✗ Timeout on options completion test - test failed"
exit 1
}
}
# Final cleanup - make sure we're at clean prompt
send "\x03"
expect "$ "
send "\r"
expect "$ "
# Exit bash cleanly
send "exit\r"
expect eof
puts "\n=== Completion Test Complete ==="
puts "PIP bash completion functionality tested!"

View File

@ -0,0 +1,40 @@
#!/bin/sh -eux
# This script requires root privileges and you should never run it on your own machine
test $EUID -eq 0
PYTHON_VERSION=$(/usr/bin/python3 -c 'import sys; print("{}.{}".format(*sys.version_info))')
RPM_SITELIB="/usr/lib/python${PYTHON_VERSION}/site-packages"
LOCAL_SITELIB="/usr/local/lib/python${PYTHON_VERSION}/site-packages"
USER_SITELIB="/home/fedora-test-user/.local/lib/python${PYTHON_VERSION}/site-packages"
# First, let's install older Pello with pip as if it was installed by RPM
# This is an approximation, but it usually works
RPM_BUILD_ROOT=/ /usr/bin/pip install 'Pello==1.0.1'
# Now, we'll upgrade it with regular pip
/usr/bin/pip install --upgrade 'Pello==1.0.2'
# pip should see it
/usr/bin/pip freeze | grep '^Pello==1\.0\.2$'
# Both installations should still exist
test -d "${RPM_SITELIB}/Pello-1.0.1-py${PYTHON_VERSION}.egg-info" || test -d "${RPM_SITELIB}/Pello-1.0.1.dist-info"
test -d "${LOCAL_SITELIB}/Pello-1.0.2.dist-info"
# Let's ditch the local one
/usr/bin/pip uninstall --yes Pello
# It should only remove one of them
test -d "${RPM_SITELIB}/Pello-1.0.1-py${PYTHON_VERSION}.egg-info" || test -d "${RPM_SITELIB}/Pello-1.0.1.dist-info"
! test -d "${LOCAL_SITELIB}/Pello-1.0.2.dist-info"
# And pip should still see the RPM-installed one
/usr/bin/pip freeze | grep '^Pello==1\.0\.1$'
# Again, but as regular user
useradd fedora-test-user
su fedora-test-user -c '/usr/bin/pip install "Pello==1.0.2"'
test -d "${USER_SITELIB}/Pello-1.0.2.dist-info"
su fedora-test-user -c '/usr/bin/pip freeze' | grep '^Pello==1\.0\.2$'
su fedora-test-user -c '/usr/bin/pip uninstall --yes Pello'
su fedora-test-user -c '/usr/bin/pip freeze' | grep '^Pello==1\.0\.1$'