Skip to content

Commit 202e90c

Browse files
committed
Use PEP 503 rules to validate upload filename
1 parent 5d0ffe5 commit 202e90c

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

tests/unit/forklift/test_legacy.py

+13-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
from cgi import FieldStorage
2121
from unittest import mock
2222

23-
import pkg_resources
2423
import pretend
2524
import pytest
2625
import requests
@@ -2388,7 +2387,16 @@ def test_upload_fails_with_diff_filename_same_blake2(
23882387
"400 File already exists. See /the/help/url/ for more information."
23892388
)
23902389

2391-
def test_upload_fails_with_wrong_filename(self, pyramid_config, db_request):
2390+
@pytest.mark.parametrize(
2391+
"filename",
2392+
[
2393+
"nope-{}.tar.gz",
2394+
"nope-{}-py3-none-any.whl",
2395+
],
2396+
)
2397+
def test_upload_fails_with_wrong_filename(
2398+
self, pyramid_config, db_request, filename
2399+
):
23922400
pyramid_config.testing_securitypolicy(userid=1)
23932401

23942402
user = UserFactory.create()
@@ -2398,7 +2406,7 @@ def test_upload_fails_with_wrong_filename(self, pyramid_config, db_request):
23982406
release = ReleaseFactory.create(project=project, version="1.0")
23992407
RoleFactory.create(user=user, project=project)
24002408

2401-
filename = "nope-{}.tar.gz".format(release.version)
2409+
filename = filename.format(release.version)
24022410

24032411
db_request.POST = MultiDict(
24042412
{
@@ -2422,8 +2430,8 @@ def test_upload_fails_with_wrong_filename(self, pyramid_config, db_request):
24222430

24232431
assert resp.status_code == 400
24242432
assert resp.status == (
2425-
"400 Start filename for {!r} with {!r}.".format(
2426-
project.name, pkg_resources.safe_name(project.name).lower()
2433+
"400 Filename {!r} must match project {!r}.".format(
2434+
filename, project.normalized_name
24272435
)
24282436
)
24292437

warehouse/forklift/legacy.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import packaging.specifiers
2727
import packaging.utils
2828
import packaging.version
29-
import pkg_resources
3029
import requests
3130
import stdlib_list
3231
import wtforms
@@ -626,6 +625,14 @@ def full_validate(self):
626625
)
627626

628627

628+
def _is_valid_filename(filename, specified_canonical_name):
629+
if filename.endswith(".whl"):
630+
parsed_canonical_name = packaging.utils.parse_wheel_filename(filename)[0]
631+
else:
632+
parsed_canonical_name = packaging.utils.parse_sdist_filename(filename)[0]
633+
return parsed_canonical_name == specified_canonical_name
634+
635+
629636
_safe_zipnames = re.compile(r"(purelib|platlib|headers|scripts|data).+", re.I)
630637
# .tar uncompressed, .tar.gz .tgz, .tar.bz2 .tbz2
631638
_tar_filenames_re = re.compile(r"\.(?:tar$|t(?:ar\.)?(?P<z_type>gz|bz2)$)")
@@ -1192,11 +1199,11 @@ def file_upload(request):
11921199

11931200
# Make sure that our filename matches the project that it is being uploaded
11941201
# to.
1195-
prefix = pkg_resources.safe_name(project.name).lower()
1196-
if not pkg_resources.safe_name(filename).lower().startswith(prefix):
1202+
canonical_name = project.normalized_name
1203+
if not _is_valid_filename(filename, canonical_name):
11971204
raise _exc_with_message(
11981205
HTTPBadRequest,
1199-
"Start filename for {!r} with {!r}.".format(project.name, prefix),
1206+
"Filename {!r} must match project {!r}.".format(filename, canonical_name),
12001207
)
12011208

12021209
# Check the content type of what is being uploaded

0 commit comments

Comments
 (0)