diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py index 4439fdad3f..1c42330451 100644 --- a/django/utils/translation/trans_real.py +++ b/django/utils/translation/trans_real.py @@ -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] diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index 65dc9952bc..d6c70a9bb0 100644 --- a/docs/ref/utils.txt +++ b/docs/ref/utils.txt @@ -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``. @@ -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) diff --git a/docs/releases/4.2.15.txt b/docs/releases/4.2.15.txt new file mode 100644 index 0000000000..a15eced1a3 --- /dev/null +++ b/docs/releases/4.2.15.txt @@ -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`). diff --git a/docs/releases/5.0.8.txt b/docs/releases/5.0.8.txt index 7bdb5488b2..0f5123f68f 100644 --- a/docs/releases/5.0.8.txt +++ b/docs/releases/5.0.8.txt @@ -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`). diff --git a/docs/releases/index.txt b/docs/releases/index.txt index 2ace2b44af..bece4a981a 100644 --- a/docs/releases/index.txt +++ b/docs/releases/index.txt @@ -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 diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py index 1bd1dadf93..8f8a33e5b0 100644 --- a/tests/i18n/tests.py +++ b/tests/i18n/tests.py @@ -1673,14 +1673,13 @@ class MiscTests(SimpleTestCase): 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 @@ -1734,6 +1733,7 @@ class MiscTests(SimpleTestCase): ("/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): @@ -2009,6 +2009,11 @@ class CountrySpecificLanguageTests(SimpleTestCase): 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")