Skip to content

Commit 8c2b4b8

Browse files
committed
don't strip leading = when parsing cookie
1 parent 7c7ce5c commit 8c2b4b8

File tree

4 files changed

+14
-9
lines changed

4 files changed

+14
-9
lines changed

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Unreleased
1919
:issue:`2529`
2020
- ``LimitedStream.read`` works correctly when wrapping a stream that may not return
2121
the requested size in one ``read`` call. :issue:`2558`
22+
- A cookie header that starts with ``=`` is treated as an empty key and discarded,
23+
rather than stripping the leading ``==``.
2224

2325

2426
Version 2.2.2

src/werkzeug/_internal.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
_legal_cookie_chars_re = rb"[\w\d!#%&\'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=]"
3535
_cookie_re = re.compile(
3636
rb"""
37-
(?P<key>[^=;]+)
37+
(?P<key>[^=;]*)
3838
(?:\s*=\s*
3939
(?P<val>
4040
"(?:[^\\"]|\\.)*" |
@@ -382,16 +382,21 @@ def _cookie_parse_impl(b: bytes) -> t.Iterator[t.Tuple[bytes, bytes]]:
382382
"""Lowlevel cookie parsing facility that operates on bytes."""
383383
i = 0
384384
n = len(b)
385+
b += b";"
385386

386387
while i < n:
387-
match = _cookie_re.search(b + b";", i)
388+
match = _cookie_re.match(b, i)
389+
388390
if not match:
389391
break
390392

391-
key = match.group("key").strip()
392-
value = match.group("val") or b""
393393
i = match.end(0)
394+
key = match.group("key").strip()
395+
396+
if not key:
397+
continue
394398

399+
value = match.group("val") or b""
395400
yield key, _cookie_unquote(value)
396401

397402

src/werkzeug/sansio/http.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,6 @@ def parse_cookie(
126126
def _parse_pairs() -> t.Iterator[t.Tuple[str, str]]:
127127
for key, val in _cookie_parse_impl(cookie): # type: ignore
128128
key_str = _to_str(key, charset, errors, allow_none_charset=True)
129-
130-
if not key_str:
131-
continue
132-
133129
val_str = _to_str(val, charset, errors, allow_none_charset=True)
134130
yield key_str, val_str
135131

tests/test_http.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,8 @@ def test_is_resource_modified_for_range_requests(self):
412412
def test_parse_cookie(self):
413413
cookies = http.parse_cookie(
414414
"dismiss-top=6; CP=null*; PHPSESSID=0a539d42abc001cdc762809248d4beed;"
415-
'a=42; b="\\";"; ; fo234{=bar;blub=Blah; "__Secure-c"=d'
415+
'a=42; b="\\";"; ; fo234{=bar;blub=Blah; "__Secure-c"=d;'
416+
"==__Host-eq=bad;__Host-eq=good;"
416417
)
417418
assert cookies.to_dict() == {
418419
"CP": "null*",
@@ -423,6 +424,7 @@ def test_parse_cookie(self):
423424
"fo234{": "bar",
424425
"blub": "Blah",
425426
'"__Secure-c"': "d",
427+
"__Host-eq": "good",
426428
}
427429

428430
def test_dump_cookie(self):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy