Skip to content

Commit

Permalink
Merge branch 'main' into accept-time-based-retry-tests-as-flaky
Browse files Browse the repository at this point in the history
  • Loading branch information
ichard26 authored Dec 7, 2024
2 parents bd3c820 + 634bf25 commit 85f0045
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 24 deletions.
1 change: 1 addition & 0 deletions news/13079.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This change fixes a security bug allowing a wheel to execute code during installation.
Empty file.
13 changes: 7 additions & 6 deletions src/pip/_internal/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
from pip._vendor.packaging.utils import canonicalize_name
from pip._vendor.rich import print_json

# Eagerly import self_outdated_check to avoid crashes. Otherwise,
# this module would be imported *after* pip was replaced, resulting
# in crashes if the new self_outdated_check module was incompatible
# with the rest of pip that's already imported, or allowing a
# wheel to execute arbitrary code on install by replacing
# self_outdated_check.
import pip._internal.self_outdated_check # noqa: F401
from pip._internal.cache import WheelCache
from pip._internal.cli import cmdoptions
from pip._internal.cli.cmdoptions import make_target_python
Expand Down Expand Up @@ -408,12 +415,6 @@ def run(self, options: Values, args: List[str]) -> int:
# If we're not replacing an already installed pip,
# we're not modifying it.
modifying_pip = pip_req.satisfied_by is None
if modifying_pip:
# Eagerly import this module to avoid crashes. Otherwise, this
# module would be imported *after* pip was replaced, resulting in
# crashes if the new self_outdated_check module was incompatible
# with the rest of pip that's already imported.
import pip._internal.self_outdated_check # noqa: F401
protect_pip_from_modification_on_windows(modifying_pip=modifying_pip)

reqs_to_build = [
Expand Down
17 changes: 17 additions & 0 deletions tests/lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
cast,
)
from urllib.parse import urlparse, urlunparse
from urllib.request import pathname2url
from zipfile import ZipFile

import pytest
Expand Down Expand Up @@ -1379,6 +1380,10 @@ def __call__(

CertFactory = Callable[[], str]

# -------------------------------------------------------------------------
# Accommodations for Windows path and URL changes in recent Python releases
# -------------------------------------------------------------------------

# versions containing fix/backport from https://github.com/python/cpython/pull/113563
# which changed the behavior of `urllib.parse.urlun{parse,split}`
url = "////path/to/file"
Expand All @@ -1394,3 +1399,15 @@ def __call__(
sys.platform != "win32" or has_new_urlun_behavior,
reason="testing windows behavior for older CPython",
)

# Trailing slashes are now preserved on Windows, matching POSIX behaviour.
# BPO: https://github.com/python/cpython/issues/126212
does_pathname2url_preserve_trailing_slash = pathname2url("C:/foo/").endswith("/")
skip_needs_new_pathname2url_trailing_slash_behavior_win = pytest.mark.skipif(
sys.platform != "win32" or not does_pathname2url_preserve_trailing_slash,
reason="testing windows (pathname2url) behavior for newer CPython",
)
skip_needs_old_pathname2url_trailing_slash_behavior_win = pytest.mark.skipif(
sys.platform != "win32" or does_pathname2url_preserve_trailing_slash,
reason="testing windows (pathname2url) behavior for older CPython",
)
20 changes: 18 additions & 2 deletions tests/unit/test_collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@
from tests.lib import (
TestData,
make_test_link_collector,
skip_needs_new_pathname2url_trailing_slash_behavior_win,
skip_needs_new_urlun_behavior_win,
skip_needs_old_pathname2url_trailing_slash_behavior_win,
skip_needs_old_urlun_behavior_win,
)

Expand Down Expand Up @@ -390,12 +392,26 @@ def test_clean_url_path_with_local_path(path: str, expected: str) -> None:
pytest.param(
"file:///T:/path/with spaces/",
"file:///T:/path/with%20spaces",
marks=skip_needs_old_urlun_behavior_win,
marks=[
skip_needs_old_urlun_behavior_win,
skip_needs_old_pathname2url_trailing_slash_behavior_win,
],
),
pytest.param(
"file:///T:/path/with spaces/",
"file://///T:/path/with%20spaces",
marks=skip_needs_new_urlun_behavior_win,
marks=[
skip_needs_new_urlun_behavior_win,
skip_needs_old_pathname2url_trailing_slash_behavior_win,
],
),
pytest.param(
"file:///T:/path/with spaces/",
"file://///T:/path/with%20spaces/",
marks=[
skip_needs_new_urlun_behavior_win,
skip_needs_new_pathname2url_trailing_slash_behavior_win,
],
),
# URL with Windows drive letter, running on non-windows
# platform. The `:` after the drive should be quoted.
Expand Down
26 changes: 10 additions & 16 deletions tests/unit/test_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@

from pip._internal.utils.urls import path_to_url, url_to_path

from tests.lib import (
skip_needs_new_urlun_behavior_win,
skip_needs_old_urlun_behavior_win,
)


@pytest.mark.skipif("sys.platform == 'win32'")
def test_path_to_url_unix() -> None:
Expand All @@ -25,23 +20,22 @@ def test_path_to_url_unix() -> None:
[
pytest.param("c:/tmp/file", "file:///C:/tmp/file", id="posix-path"),
pytest.param("c:\\tmp\\file", "file:///C:/tmp/file", id="nt-path"),
pytest.param(
r"\\unc\as\path",
"file://unc/as/path",
marks=skip_needs_old_urlun_behavior_win,
id="unc-path",
),
pytest.param(
r"\\unc\as\path",
"file:////unc/as/path",
marks=skip_needs_new_urlun_behavior_win,
),
],
)
def test_path_to_url_win(path: str, url: str) -> None:
assert path_to_url(path) == url


@pytest.mark.skipif("sys.platform != 'win32'")
def test_unc_path_to_url_win() -> None:
# The two and four slash forms are both acceptable for our purposes. CPython's
# behaviour has changed several times here, so blindly accept either.
# - https://github.com/python/cpython/issues/78457
# - https://github.com/python/cpython/issues/126205
url = path_to_url(r"\\unc\as\path")
assert url in ["file://unc/as/path", "file:////unc/as/path"]


@pytest.mark.skipif("sys.platform != 'win32'")
def test_relative_path_to_url_win() -> None:
resolved_path = os.path.join(os.getcwd(), "file")
Expand Down

0 comments on commit 85f0045

Please sign in to comment.