nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: pallets/werkzeug
Pull request #2350 (2022-03-16 14:44:44)

routing match includes newline
The `$` in regular expressions will match *before and after* a newline character. WSGI requires the server to decode `PATH_INFO`, which can result in a requested URL `/hello%0a` looking like `/hello\n` to the application. If you have some middleware that intercepts `/hello`, depending on how it does that, this could result in the application handling the URL instead.

Use `\Z` instead of `$` to match only the true end of the string.


Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index aebda9f0..aa51f4ad 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 cf5baf0e..49e4449e 100644
--- a/src/werkzeug/routing.py
+++ b/src/werkzeug/routing.py
@@ -666,6 +666,11 @@ class Rule(RuleFactory):
         ``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 @@ class Rule(RuleFactory):
         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(


Test patch:
diff --git a/tests/test_routing.py b/tests/test_routing.py
index e8c7a429..6544d89b 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")
Repository: pallets/werkzeug
Pull request #2470 (2022-07-26 18:22:22)

Bugfix ensure that the entire part is matched
Checklist:

- [x] Add tests that demonstrate the correct behavior of the change. Tests should fail without the change.
- [x] Add or update relevant docs, in the docs folder and in code.
- [x] Add an entry in `CHANGES.rst` summarizing the change and linking to the issue.
- [x] Add `.. versionchanged::` entries in any relevant code docs.
- [x] Run `pre-commit` hooks and fix any issues.
- [x] Run `pytest` and `tox`, no tests failed.



Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 662bf0cc..70d7b971 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -7,6 +7,8 @@ Unreleased
 
 -   Fix router so that ``/path/`` will match a rule ``/path`` if strict
     slashes mode is disabled for the rule. :issue:`2467`
+-   Fix router so that partial part matches are not allowed
+    i.e. ``/2df`` does not match ``/<int>``. :pr:`2470`
 -   Restore ``ValidationError`` to be importable from
     ``werkzeug.routing``. :issue:`2465`
 
diff --git a/src/werkzeug/routing/rules.py b/src/werkzeug/routing/rules.py
index f16e5668..29c78568 100644
--- a/src/werkzeug/routing/rules.py
+++ b/src/werkzeug/routing/rules.py
@@ -625,8 +625,8 @@ class Rule(RuleFactory):
                     -len(argument_weights),
                     argument_weights,
                 )
-                if final:
-                    content += r"$\Z"
+                if not static:
+                    content += r"\Z"
                 yield RulePart(
                     content=content, final=final, static=static, weight=weight
                 )


Test patch:
diff --git a/tests/test_routing.py b/tests/test_routing.py
index 0c28a186..4f9fc2cc 100644
--- a/tests/test_routing.py
+++ b/tests/test_routing.py
@@ -1400,3 +1400,18 @@ def test_newline_match():
 
     with pytest.raises(NotFound):
         a.match("/hello\n")
+
+
+def test_weighting():
+    m = r.Map(
+        [
+            r.Rule("/<int:value>", endpoint="int"),
+            r.Rule("/<uuid:value>", endpoint="uuid"),
+        ]
+    )
+    a = m.bind("localhost")
+
+    assert a.match("/2b5b0911-fdcf-4dd2-921b-28ace88db8a0") == (
+        "uuid",
+        {"value": uuid.UUID("2b5b0911-fdcf-4dd2-921b-28ace88db8a0")},
+    )
Repository: pallets/werkzeug
Pull request #2532 (2022-10-12 12:12:53)

check length validity before calling ds.ContentRange
Check if the length of ContentRange is valid before creating the object to avoid the AssertionError generated otherwise.

- fixes https://github.com/pallets/werkzeug/issues/2531

Checklist:

- [x] Add tests that demonstrate the correct behavior of the change. Tests should fail without the change.
- [-] Add or update relevant docs, in the docs folder and in code.
- [x] Add an entry in `CHANGES.rst` summarizing the change and linking to the issue.
- [ ] Add `.. versionchanged::` entries in any relevant code docs.
- [x] Run `pre-commit` hooks and fix any issues.
- [x] Run `pytest` and `tox`, no tests failed.



Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index fd9935b2..e90bedcc 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -7,6 +7,8 @@ Unreleased
 
 -   Type signature for ``get_json`` specifies that return type is not optional when
     ``silent=False``. :issue:`2508`
+-   ``parse_content_range_header`` returns ``None`` for a value like ``bytes */-1``
+    where the length is invalid, instead of raising an ``AssertionError``. :issue:`2531`
 
 
 Version 2.2.2
diff --git a/src/werkzeug/http.py b/src/werkzeug/http.py
index 97776855..93d9536e 100644
--- a/src/werkzeug/http.py
+++ b/src/werkzeug/http.py
@@ -818,6 +818,9 @@ def parse_content_range_header(
             return None
 
     if rng == "*":
+        if not is_byte_range_valid(None, None, length):
+            return None
+
         return ds.ContentRange(units, None, None, length, on_update=on_update)
     elif "-" not in rng:
         return None


Test patch:
diff --git a/tests/test_http.py b/tests/test_http.py
index 3760dc12..0f94a38c 100644
--- a/tests/test_http.py
+++ b/tests/test_http.py
@@ -619,6 +619,9 @@ class TestRange:
         rv = http.parse_content_range_header("bytes 0-98/*asdfsa")
         assert rv is None
 
+        rv = http.parse_content_range_header("bytes */-1")
+        assert rv is None
+
         rv = http.parse_content_range_header("bytes 0-99/100")
         assert rv.to_header() == "bytes 0-99/100"
         rv.start = None