Skip to content

Commit 399bb08

Browse files
committed
Avoid validating twice parsed header values.
Fix #1714.
1 parent cd0b72d commit 399bb08

3 files changed

Lines changed: 21 additions & 1 deletion

File tree

src/websockets/datastructures.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,16 @@ def raw_items(self) -> Iterator[tuple[str, str]]:
165165
"""
166166
return iter(self._list)
167167

168+
# Internal menthods
169+
170+
def set_insecure(self, key: str, value: str) -> None:
171+
"""
172+
Set a header without validating its value.
173+
174+
"""
175+
self._dict.setdefault(key.lower(), []).append(value)
176+
self._list.append((key, value))
177+
168178

169179
# copy of _typeshed.SupportsKeysAndGetItem.
170180
class SupportsKeysAndGetItem(Protocol): # pragma: no cover

src/websockets/http11.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,9 @@ def parse_headers(
369369

370370
name = raw_name.decode("ascii") # guaranteed to be ASCII at this point
371371
value = raw_value.decode("ascii", "surrogateescape")
372-
headers[name] = value
372+
373+
# Since we just validated raw_value, we don't need to revalidate it.
374+
headers.set_insecure(name, value)
373375

374376
else:
375377
raise SecurityError("too many HTTP headers")

tests/test_datastructures.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,14 @@ def test_raw_items(self):
173173
[("Connection", "Upgrade"), ("Server", "websockets")],
174174
)
175175

176+
def test_set_insecure(self):
177+
self.headers.set_insecure("Upgrade", "websocket")
178+
self.assertEqual(self.headers["Upgrade"], "websocket")
179+
180+
def test_set_insecure_invalid_value(self):
181+
self.headers.set_insecure("X-Invalid", "multi\r\nline")
182+
self.assertEqual(self.headers["X-Invalid"], "multi\r\nline") # oops
183+
176184

177185
class MultiValueHeadersTests(unittest.TestCase):
178186
def setUp(self):

0 commit comments

Comments
 (0)