Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-143916: Allow HTAB in wsgiref header values#144118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
sethmlarson wants to merge1 commit intopython:main
base:main
Choose a base branch
Loading
fromsethmlarson:allow-htab-in-http-headers
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletionsLib/test/test_wsgiref.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -504,14 +504,20 @@ def testExtras(self):
)

def testRaisesControlCharacters(self):
headers = Headers()
for c0 in control_characters_c0():
self.assertRaises(ValueError, headers.__setitem__, f"key{c0}", "val")
self.assertRaises(ValueError, headers.__setitem__, "key", f"val{c0}")
self.assertRaises(ValueError, headers.add_header, f"key{c0}", "val", param="param")
self.assertRaises(ValueError, headers.add_header, "key", f"val{c0}", param="param")
self.assertRaises(ValueError, headers.add_header, "key", "val", param=f"param{c0}")

with self.subTest(c0):
headers = Headers()
self.assertRaises(ValueError, headers.__setitem__, f"key{c0}", "val")
self.assertRaises(ValueError, headers.add_header, f"key{c0}", "val", param="param")
# HTAB is allowed in values, not names.
if c0 == "\t":
headers["key"] = f"val{c0}"
headers.add_header("key", f"val{c0}")
headers.setdefault(f"key", f"val{c0}")
else:
self.assertRaises(ValueError, headers.__setitem__, "key", f"val{c0}")
self.assertRaises(ValueError, headers.add_header, "key", f"val{c0}", param="param")
self.assertRaises(ValueError, headers.add_header, "key", "val", param=f"param{c0}")

class ErrorHandler(BaseCGIHandler):
"""Simple handler subclass for testing BaseHandler"""
Expand Down
26 changes: 15 additions & 11 deletionsLib/wsgiref/headers.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,7 +9,11 @@
# existence of which force quoting of the parameter value.
import re
tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
_control_chars_re = re.compile(r'[\x00-\x1F\x7F]')
# Disallowed characters for headers and values.
# HTAB (\x09) is allowed in header values, but
# not in header names. (RFC 9110 Section 5.5)
_name_disallowed_re = re.compile(r'[\x00-\x1F\x7F]')
_value_disallowed_re = re.compile(r'[\x00-\x08\x0A-\x1F\x7F]')

def _formatparam(param, value=None, quote=1):
"""Convenience function to format and return a key=value pair.
Expand All@@ -36,13 +40,13 @@ def __init__(self, headers=None):
self._headers = headers
if __debug__:
for k, v in headers:
self._convert_string_type(k)
self._convert_string_type(k, name=True)
self._convert_string_type(v)

def _convert_string_type(self, value):
def _convert_string_type(self, value, *, name=False):
"""Convert/check value type."""
if type(value) is str:
if_control_chars_re.search(value):
if(_name_disallowed_re if name else _value_disallowed_re).search(value):
raise ValueError("Control characters not allowed in headers")
return value
raise AssertionError("Header names/values must be"
Expand All@@ -56,14 +60,14 @@ def __setitem__(self, name, val):
"""Set the value of a header."""
del self[name]
self._headers.append(
(self._convert_string_type(name), self._convert_string_type(val)))
(self._convert_string_type(name, name=True), self._convert_string_type(val)))

def __delitem__(self,name):
"""Delete all occurrences of a header, if present.

Does *not* raise an exception if the header is missing.
"""
name = self._convert_string_type(name.lower())
name = self._convert_string_type(name.lower(), name=True)
self._headers[:] = [kv for kv in self._headers if kv[0].lower() != name]

def __getitem__(self,name):
Expand All@@ -90,13 +94,13 @@ def get_all(self, name):
fields deleted and re-inserted are always appended to the header list.
If no fields exist with the given name, returns an empty list.
"""
name = self._convert_string_type(name.lower())
name = self._convert_string_type(name.lower(), name=True)
return [kv[1] for kv in self._headers if kv[0].lower()==name]


def get(self,name,default=None):
"""Get the first header value for 'name', or return 'default'"""
name = self._convert_string_type(name.lower())
name = self._convert_string_type(name.lower(), name=True)
for k,v in self._headers:
if k.lower()==name:
return v
Expand DownExpand Up@@ -151,7 +155,7 @@ def setdefault(self,name,value):
and value 'value'."""
result = self.get(name)
if result is None:
self._headers.append((self._convert_string_type(name),
self._headers.append((self._convert_string_type(name, name=True),
self._convert_string_type(value)))
return value
else:
Expand All@@ -178,10 +182,10 @@ def add_header(self, _name, _value, **_params):
_value = self._convert_string_type(_value)
parts.append(_value)
for k, v in _params.items():
k = self._convert_string_type(k)
k = self._convert_string_type(k, name=True)
if v is None:
parts.append(k.replace('_', '-'))
else:
v = self._convert_string_type(v)
parts.append(_formatparam(k.replace('_', '-'), v))
self._headers.append((self._convert_string_type(_name), "; ".join(parts)))
self._headers.append((self._convert_string_type(_name, name=True), "; ".join(parts)))
Loading

[8]ページ先頭

©2009-2026 Movatter.jp