]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Invert web.RequestHandler._INVALID_HEADER_CHAR_RE 3451/head
authorDave Shawley <daveshawley@gmail.com>
Fri, 27 Dec 2024 22:24:19 +0000 (17:24 -0500)
committerDave Shawley <daveshawley@gmail.com>
Fri, 27 Dec 2024 22:24:19 +0000 (17:24 -0500)
This makes the expression match what is in the RFC. I also added a test
for empty header values since I messed up the RE the first time around.

tornado/test/web_test.py
tornado/web.py

index d99a66a408a4c6daad5357d6b5888f76db31dceb..45bf211b2b14549741e4167ae094d405d1084848 100644 (file)
@@ -708,9 +708,7 @@ class HeaderInjectionHandler(RequestHandler):
 
 class SetHeaderHandler(RequestHandler):
     def get(self):
-        # tests the validity of web.RequestHandler._INVALID_HEADER_CHAR_RE
-        # should match the invalid characters from
-        # https://www.rfc-editor.org/rfc/rfc9110#name-field-values
+        # tests the validity of web.RequestHandler._VALID_HEADER_CHARS
         illegal_chars = [chr(o) for o in range(0, 0x20)]
         illegal_chars.append(chr(0x7f))
         illegal_chars.remove('\t')
@@ -721,6 +719,10 @@ class SetHeaderHandler(RequestHandler):
             except ValueError as e:
                 if "Unsafe header value" not in str(e):
                     raise
+
+        # an empty header value is valid as well
+        self.set_header("X-Foo", "")
+
         self.finish(b"ok")
 
 
index b61195902eddb9eeb757ca4394638b06a0938a96..a0949572a386a13d183a62d7b495c220fc187dba 100644 (file)
@@ -399,7 +399,8 @@ class RequestHandler:
         if name in self._headers:
             del self._headers[name]
 
-    _INVALID_HEADER_CHAR_RE = re.compile(r"[\x00-\x08\x0a-\x1f\x7f]")
+    # https://www.rfc-editor.org/rfc/rfc9110#name-field-values
+    _VALID_HEADER_CHARS = re.compile(r"[\x09\x20-\x7e\x80-\xff]*")
 
     def _convert_header_value(self, value: _HeaderTypes) -> str:
         # Convert the input value to a str. This type check is a bit
@@ -421,7 +422,7 @@ class RequestHandler:
             raise TypeError("Unsupported header value %r" % value)
         # If \n is allowed into the header, it is possible to inject
         # additional headers or split the request.
-        if RequestHandler._INVALID_HEADER_CHAR_RE.search(retval):
+        if RequestHandler._VALID_HEADER_CHARS.fullmatch(retval) is None:
             raise ValueError("Unsafe header value %r", retval)
         return retval