Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restrict #egg= fragments to valid PEP 508 names #11617

Merged
merged 12 commits into from
Dec 28, 2022
8 changes: 8 additions & 0 deletions src/pip/_internal/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -658,3 +658,11 @@ def __str__(self) -> str:
assert self.error is not None
message_part = f".\n{self.error}\n"
return f"Configuration file {self.reason}{message_part}"


class InvalidEggFragment(InstallationError):
"""A link's `#egg=` fragment doesn't look like a valid PEP 508 project
name."""

def __init__(self, fragment: str) -> None:
super().__init__(f"egg fragment is not a bare project name: {fragment}")
16 changes: 15 additions & 1 deletion src/pip/_internal/models/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
Union,
)

from pip._internal.exceptions import InvalidEggFragment
from pip._internal.utils.filetypes import WHEEL_EXTENSION
from pip._internal.utils.hashes import Hashes
from pip._internal.utils.misc import (
Expand Down Expand Up @@ -358,12 +359,25 @@ def url_without_fragment(self) -> str:

_egg_fragment_re = re.compile(r"[#&]egg=([^&]*)")

# Per PEP 508.
_project_name_re = re.compile(
r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.IGNORECASE
)

@property
def egg_fragment(self) -> Optional[str]:
match = self._egg_fragment_re.search(self._url)
if not match:
return None
return match.group(1)

# The egg fragment must look like a project name, and only
# a project name. In particular, it can't contain version constraints
# or anything else like that.
project_name = match.group(1)
if not self._project_name_re.match(project_name):
raise InvalidEggFragment(project_name)

return project_name

_subdirectory_fragment_re = re.compile(r"[#&]subdirectory=([^&]*)")

Expand Down