From: Dave Shawley Date: Fri, 27 Dec 2024 22:24:19 +0000 (-0500) Subject: Invert web.RequestHandler._INVALID_HEADER_CHAR_RE X-Git-Tag: v6.5.0b1~19^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F3451%2Fhead;p=thirdparty%2Ftornado.git Invert web.RequestHandler._INVALID_HEADER_CHAR_RE 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. --- diff --git a/tornado/test/web_test.py b/tornado/test/web_test.py index d99a66a4..45bf211b 100644 --- a/tornado/test/web_test.py +++ b/tornado/test/web_test.py @@ -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") diff --git a/tornado/web.py b/tornado/web.py index b6119590..a0949572 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -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