Skip to content

fix: decode percent-encoded unreserved chars before resolving dot segments in normalize#195

Open
gaoflow wants to merge 1 commit into
python-hyper:masterfrom
gaoflow:fix-normalize-percent-encoded-dots
Open

fix: decode percent-encoded unreserved chars before resolving dot segments in normalize#195
gaoflow wants to merge 1 commit into
python-hyper:masterfrom
gaoflow:fix-normalize-percent-encoded-dots

Conversation

@gaoflow

@gaoflow gaoflow commented Jun 28, 2026

Copy link
Copy Markdown

Summary

URL.normalize() resolves dot segments (. and ..) before decoding percent-encoded unreserved characters. Per RFC 3986 Section 6.2.2.2, this order is incorrect -- unreserved characters should be decoded first.

For example, %2e is the percent-encoded form of . (a period is an unreserved character). The path /%2e%2e/foo should be normalized to /foo, but currently it normalizes to /../foo.

Before

>>> URL.from_text("http://example.com/%2e%2e/foo").normalize().to_text()
'http://example.com/../foo'

After

>>> URL.from_text("http://example.com/%2e%2e/foo").normalize().to_text()
'http://example.com/foo'

Test plan

  • Added test_normalize_percent_encoded_dot_segments covering three cases:
    • %2e%2e (double-dot parent reference)
    • %2e (single-dot current directory reference)
    • foo/%2e%2e/bar (encoded parent traversal in middle of path)
  • All 102 tests pass (101 existing + 1 new)

This PR was written under human direction (gaoflow).

…ments in normalize

RFC 3986 Section 6.2.2.2 specifies that percent-encoded unreserved
characters should be decoded before applying other normalizations,
including dot-segment resolution. The previous order (resolve-then-decode)
meant that %2e%2e was not recognized as ".." during path normalization,
producing incorrect results like http://example.com/../foo instead of
http://example.com/foo.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant