Skip to content

Commit 7993203

Browse files
committed
Fix 63-character limit for simple hostname labels
1 parent 22786cc commit 7993203

3 files changed

Lines changed: 27 additions & 3 deletions

File tree

‎src/validators/hostname.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ def _port_regex():
2424
@lru_cache
2525
def _simple_hostname_regex():
2626
"""Simple hostname validation regex."""
27-
# {0,59} because two characters are already matched at
28-
# the beginning and at the end, making the range {1, 61}
27+
# RFC 1035 limits each label to 63 octets. The first and last
28+
# characters leave room for up to 61 characters in between.
2929
return re.compile(
30-
r"^(?!-)[a-z0-9](?:[a-z0-9-]{0,59}[a-z0-9])?(?<!-)$", re.IGNORECASE | re.ASCII
30+
r"^(?!-)[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?<!-)$", re.IGNORECASE | re.ASCII
3131
)
3232

3333

‎tests/test_hostname.py‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,16 @@ def test_returns_true_on_valid_top_level_domain_hostname(value: str):
171171
def test_returns_failed_validation_on_invalid_top_level_domain_hostname(value: str):
172172
"""Test returns failed validation on hostname with a TLD not allowed by IANA."""
173173
assert isinstance(hostname(value, consider_tld=True), ValidationError)
174+
175+
176+
@pytest.mark.parametrize("length", [1, 61, 62, 63, 64])
177+
@pytest.mark.parametrize("port", ["", ":8080"])
178+
@pytest.mark.parametrize("rfc_1034", [False, True])
179+
def test_simple_hostname_label_length(length: int, port: str, rfc_1034: bool):
180+
"""Allow single labels up to 63 characters, with optional dots and ports."""
181+
value = "a" * length + ("." if rfc_1034 else "") + port
182+
result = hostname(value, rfc_1034=rfc_1034)
183+
if length <= 63:
184+
assert result is True
185+
else:
186+
assert isinstance(result, ValidationError)

‎tests/test_url.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,14 @@ def test_returns_true_on_valid_top_level_domain_url(value: str):
299299
def test_returns_failed_validation_on_invalid_top_level_domain_url(value: str):
300300
"""Test returns failed validation on url with a TLD not allowed by IANA."""
301301
assert isinstance(url(value, consider_tld=True), ValidationError)
302+
303+
304+
@pytest.mark.parametrize("length", [61, 62, 63, 64])
305+
@pytest.mark.parametrize("port", ["", ":8080"])
306+
def test_url_simple_hostname_label_length(length: int, port: str):
307+
"""Apply the 63-character label limit to URLs allowing simple hosts."""
308+
result = url("http://" + "a" * length + port + "/", simple_host=True)
309+
if length <= 63:
310+
assert result is True
311+
else:
312+
assert isinstance(result, ValidationError)

0 commit comments

Comments
 (0)