Skip to content

Commit dc467fd

Browse files
DineshThumma9jacobtylerwalls
authored andcommitted
Fixed #36991 -- Raised BadRequest for invalid encodings in Content-Type headers.
1 parent e1bdebc commit dc467fd

4 files changed

Lines changed: 39 additions & 4 deletions

File tree

django/http/request.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,12 @@ def accepts(self, media_type):
155155

156156
def _set_content_type_params(self, meta):
157157
"""Set content_type, content_params, and encoding."""
158-
self.content_type, self.content_params = parse_header_parameters(
159-
meta.get("CONTENT_TYPE", "")
160-
)
158+
try:
159+
self.content_type, self.content_params = parse_header_parameters(
160+
meta.get("CONTENT_TYPE", "")
161+
)
162+
except ValueError as exc:
163+
raise BadRequest("Invalid Content-Type header.") from exc
161164
if "charset" in self.content_params:
162165
try:
163166
codecs.lookup(self.content_params["charset"])

django/utils/http.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,11 @@ def parse_header_parameters(line, max_length=MAX_HEADER_LENGTH):
366366
value = value.replace("\\\\", "\\").replace('\\"', '"')
367367
if has_encoding:
368368
encoding, lang, value = value.split("'")
369-
value = unquote(value, encoding=encoding)
369+
try:
370+
value = unquote(value, encoding=encoding)
371+
except (LookupError, UnicodeDecodeError):
372+
msg = f"Invalid encoding {encoding!r} for RFC 2231 param."
373+
raise ValueError(msg)
370374
pdict[name] = value
371375
return key, pdict
372376

tests/requests_tests/tests.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,20 @@ def test_body_after_POST_multipart_form_data(self):
456456
with self.assertRaises(RawPostDataException):
457457
request.body
458458

459+
def test_malformed_header(self):
460+
tests = [
461+
# Invalid encoding name with percent-encoded value
462+
"text/plain; charset*=BOGUS''%20",
463+
# Another invalid encoding with different value
464+
"text/plain; filename*=INVALID''%s%s%s",
465+
# Invalid encoding with multi-line encoded content
466+
"text/plain; title*=NOTACODEC''%E2%80%A6",
467+
]
468+
msg = "Invalid Content-Type header."
469+
for header in tests:
470+
with self.subTest(header=header), self.assertRaisesMessage(BadRequest, msg):
471+
WSGIRequest({"REQUEST_METHOD": "GET", "CONTENT_TYPE": header})
472+
459473
def test_malformed_multipart_header(self):
460474
tests = [
461475
('Content-Disposition : form-data; name="name"', {"name": ["value"]}),

tests/utils_tests/test_http.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,20 @@ def test_rfc2231_wrong_title(self):
521521
parsed = parse_header_parameters(raw_line)
522522
self.assertEqual(parsed[1]["title"], expected_title)
523523

524+
def test_rfc2231_invalid_encoding(self):
525+
test_data = [
526+
# Invalid encoding name with percent-encoded value
527+
"text/plain; charset*=BOGUS''%20",
528+
# Another invalid encoding with different value
529+
"text/plain; filename*=INVALID''%s%s%s",
530+
# Invalid encoding with multi-line encoded content
531+
"text/plain; title*=NOTACODEC''%E2%80%A6",
532+
]
533+
msg = "Invalid encoding"
534+
for header in test_data:
535+
with self.subTest(raw_line=header), self.assertRaisesRegex(ValueError, msg):
536+
parse_header_parameters(header)
537+
524538
def test_header_max_length(self):
525539
base_header = "Content-Type: application/x-stuff; title*="
526540
base_header_len = len(base_header)

0 commit comments

Comments
 (0)