Skip to content

Commit

Permalink
Fixed #35627 -- Raised a LookupError rather than an unhandled ValueEr…
Browse files Browse the repository at this point in the history
…ror in get_supported_language_variant().

LocaleMiddleware didn't handle the ValueError raised by
get_supported_language_variant() when language codes were
over 500 characters.

Regression in 9e97922.
  • Loading branch information
lorinkoz authored and sarahboyce committed Jul 25, 2024
1 parent 2c024c9 commit 0e94f29
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 7 deletions.
2 changes: 1 addition & 1 deletion django/utils/translation/trans_real.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ def get_supported_language_variant(lang_code, strict=False):
# There is a generic variant under the maximum length accepted length.
lang_code = lang_code[:index]
else:
raise ValueError("'lang_code' exceeds the maximum accepted length")
raise LookupError(lang_code)
# If 'zh-hant-tw' is not supported, try special fallback or subsequent
# language codes i.e. 'zh-hant' and 'zh'.
possible_lang_codes = [lang_code]
Expand Down
6 changes: 3 additions & 3 deletions docs/ref/utils.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1148,7 +1148,7 @@ For a complete discussion on the usage of the following see the
``'es-ar'`` isn't.

``lang_code`` has a maximum accepted length of 500 characters. A
:exc:`ValueError` is raised if ``lang_code`` exceeds this limit and
:exc:`LookupError` is raised if ``lang_code`` exceeds this limit and
``strict`` is ``True``, or if there is no generic variant and ``strict``
is ``False``.

Expand All @@ -1160,10 +1160,10 @@ For a complete discussion on the usage of the following see the

Raises :exc:`LookupError` if nothing is found.

.. versionchanged:: 4.2.14
.. versionchanged:: 4.2.15

In older versions, ``lang_code`` values over 500 characters were
processed without raising a :exc:`ValueError`.
processed without raising a :exc:`LookupError`.

.. function:: to_locale(language)

Expand Down
14 changes: 14 additions & 0 deletions docs/releases/4.2.15.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
===========================
Django 4.2.15 release notes
===========================

*Expected August 6, 2024*

Django 4.2.15 fixes a regression in 4.2.14.

Bugfixes
========

* Fixed a regression in Django 4.2.14 that caused a crash in
``LocaleMiddleware`` when processing a language code over 500 characters
(:ticket:`35627`).
4 changes: 4 additions & 0 deletions docs/releases/5.0.8.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@ Bugfixes
* Fixed a crash when creating a model with a ``Field.db_default`` and a
``Meta.constraints`` constraint composed of ``__endswith``, ``__startswith``,
or ``__contains`` lookups (:ticket:`35625`).

* Fixed a regression in Django 5.0.7 that caused a crash in
``LocaleMiddleware`` when processing a language code over 500 characters
(:ticket:`35627`).
1 change: 1 addition & 0 deletions docs/releases/index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ versions of the documentation contain the release notes for any later releases.
.. toctree::
:maxdepth: 1

4.2.15
4.2.14
4.2.13
4.2.12
Expand Down
11 changes: 8 additions & 3 deletions tests/i18n/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1673,14 +1673,13 @@ def test_get_supported_language_variant_real(self):
g("xyz")
with self.assertRaises(LookupError):
g("xy-zz")
msg = "'lang_code' exceeds the maximum accepted length"
with self.assertRaises(LookupError):
g("x" * LANGUAGE_CODE_MAX_LENGTH)
with self.assertRaisesMessage(ValueError, msg):
with self.assertRaises(LookupError):
g("x" * (LANGUAGE_CODE_MAX_LENGTH + 1))
# 167 * 3 = 501 which is LANGUAGE_CODE_MAX_LENGTH + 1.
self.assertEqual(g("en-" * 167), "en")
with self.assertRaisesMessage(ValueError, msg):
with self.assertRaises(LookupError):
g("en-" * 167, strict=True)
self.assertEqual(g("en-" * 30000), "en") # catastrophic test

Expand Down Expand Up @@ -1734,6 +1733,7 @@ def test_get_language_from_path_real(self):
("/i-mingo/", "i-mingo"),
("/kl-tunumiit/", "kl-tunumiit"),
("/nan-hani-tw/", "nan-hani-tw"),
(f"/{'a' * 501}/", None),
]
for path, language in tests:
with self.subTest(path=path):
Expand Down Expand Up @@ -2009,6 +2009,11 @@ def test_get_language_from_request(self):
lang = get_language_from_request(request)
self.assertEqual("bg", lang)

def test_get_language_from_request_code_too_long(self):
request = self.rf.get("/", headers={"accept-language": "a" * 501})
lang = get_language_from_request(request)
self.assertEqual("en-us", lang)

def test_get_language_from_request_null(self):
lang = trans_null.get_language_from_request(None)
self.assertEqual(lang, "en")
Expand Down

0 comments on commit 0e94f29

Please sign in to comment.