Skip to content

Commit

Permalink
Fix qvalue parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Julian Faude committed Jul 20, 2023
1 parent 4048509 commit 17d88b7
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Version 2.3.7
Unreleased

- Use ``flit_core`` instead of ``setuptools`` as build backend.
- Fix ``parse_options_header`` rejects q values "0" and "1". :issue:`2751`


Version 2.3.6
Expand Down
9 changes: 9 additions & 0 deletions src/werkzeug/_internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ def _decode_idna(domain: str) -> str:

_plain_int_re = re.compile(r"-?\d+", re.ASCII)
_plain_float_re = re.compile(r"-?\d+\.\d+", re.ASCII)
_plain_qvalue_re = re.compile(r"(1(\.0{0,3})?)|(0(\.\d{0,3})?)", re.ASCII)


def _plain_int(value: str) -> int:
Expand All @@ -339,3 +340,11 @@ def _plain_float(value: str) -> float:
raise ValueError

return float(value)


def _qvalue(value: str) -> float:
"""Parse a RFC9110 quality value"""
if _plain_qvalue_re.fullmatch(value) is None:
raise ValueError

return float(value)
4 changes: 2 additions & 2 deletions src/werkzeug/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
from urllib.request import parse_http_list as _parse_list_header

from ._internal import _dt_as_utc
from ._internal import _plain_float
from ._internal import _plain_int
from ._internal import _qvalue

if t.TYPE_CHECKING:
from _typeshed.wsgi import WSGIEnvironment
Expand Down Expand Up @@ -658,7 +658,7 @@ def parse_accept_header(
if "q" in options:
try:
# pop q, remaining options are reconstructed
q = _plain_float(options.pop("q"))
q = _qvalue(options.pop("q"))
except ValueError:
# ignore an invalid q
continue
Expand Down
6 changes: 6 additions & 0 deletions tests/test_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,12 @@ def test_accept_invalid_float(value):
assert list(a.values()) == ["en"]


def test_accept_valid_int_one_zero():
assert http.parse_accept_header("en;q=1") == http.parse_accept_header("en;q=1.0")
assert http.parse_accept_header("en;q=0") == http.parse_accept_header("en;q=0.0")
assert http.parse_accept_header("en;q=5") == http.parse_accept_header("en;q=5.0")


@pytest.mark.parametrize("value", ["🯱🯲🯳", "+1-", "1-1_23"])
def test_range_invalid_int(value):
assert http.parse_range_header(value) is None
Expand Down

0 comments on commit 17d88b7

Please sign in to comment.