From d761d0e7acceb89f56d76434a74aeacf95d5ed49 Mon Sep 17 00:00:00 2001 From: David Lord Date: Wed, 16 Mar 2022 07:40:54 -0700 Subject: [PATCH] routing match includes newline --- CHANGES.rst | 3 +++ src/werkzeug/routing.py | 9 ++++++++- tests/test_routing.py | 8 ++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index aebda9f05..aa51f4ad5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -83,6 +83,9 @@ Unreleased instead of bytes. :pr:`2337` - ``safe_join`` ensures that the path remains relative if the trusted directory is the empty string. :pr:`2349` +- Percent-encoded newlines (``%0a``), which are decoded by WSGI + servers, are considered when routing instead of terminating the + match early. :pr:`2350` Version 2.0.3 diff --git a/src/werkzeug/routing.py b/src/werkzeug/routing.py index cf5baf0e3..49e4449e1 100644 --- a/src/werkzeug/routing.py +++ b/src/werkzeug/routing.py @@ -666,6 +666,11 @@ def foo_with_slug(adapter, id): ``wss://``) requests. By default, rules will only match for HTTP requests. + .. versionchanged:: 2.1 + Percent-encoded newlines (``%0a``), which are decoded by WSGI + servers, are considered when routing instead of terminating the + match early. + .. versionadded:: 1.0 Added ``websocket``. @@ -892,7 +897,9 @@ def _build_regex(rule: str) -> None: else: tail = "" - regex = f"^{''.join(regex_parts)}{tail}$" + # Use \Z instead of $ to avoid matching before a %0a decoded to + # a \n by WSGI. + regex = rf"^{''.join(regex_parts)}{tail}$\Z" self._regex = re.compile(regex) def match( diff --git a/tests/test_routing.py b/tests/test_routing.py index e8c7a4299..6544d89b2 100644 --- a/tests/test_routing.py +++ b/tests/test_routing.py @@ -1346,3 +1346,11 @@ def test_rule_websocket_methods(): methods=["get", "head", "options", "post"], ) r.Rule("/ws", endpoint="ws", websocket=True, methods=["get", "head", "options"]) + + +def test_newline_match(): + m = r.Map([r.Rule("/hello", endpoint="hello")]) + a = m.bind("localhost") + + with pytest.raises(r.NotFound): + a.match("/hello\n")