diff options
| author | Sean Reed <sean@sean-reed.com> | 2025-12-19 22:09:25 +0100 |
|---|---|---|
| committer | Natalia <124304+nessita@users.noreply.github.com> | 2025-12-24 14:48:16 -0300 |
| commit | 16107ab710dc23d5ea0aa17da6bf29fe89b61bb0 (patch) | |
| tree | f9d3376b3cb66d1c309b6578dbaf54126960ec4b | |
| parent | 774543ed4feb37916071e81c0d0b81ba514333fa (diff) | |
[6.0.x] Refs #36810 -- Avoided infinite recursion in LazyNonce.__repr__().
Moved nonce generation in ``django.utils.csp.LazyNonce`` to a function
to avoid infinite recursion in ``SimpleLazyObject.__repr__`` for
unevaluated instances.
Co-authored-by: Natalia <124304+nessita@users.noreply.github.com>
Backport of 165c3599965e63f88649a46fcc2ff681c52f2f66 from main.
| -rw-r--r-- | django/utils/csp.py | 9 | ||||
| -rw-r--r-- | docs/releases/6.0.1.txt | 4 | ||||
| -rw-r--r-- | tests/utils_tests/test_csp.py | 10 |
3 files changed, 18 insertions, 5 deletions
diff --git a/django/utils/csp.py b/django/utils/csp.py index d57fc98995..08a9d0752e 100644 --- a/django/utils/csp.py +++ b/django/utils/csp.py @@ -71,15 +71,16 @@ class LazyNonce(SimpleLazyObject): """ def __init__(self): - super().__init__(self._generate) - - def _generate(self): - return secrets.token_urlsafe(16) + super().__init__(generate_nonce) def __bool__(self): return self._wrapped is not empty +def generate_nonce(): + return secrets.token_urlsafe(16) + + def build_policy(config, nonce=None): policy = [] diff --git a/docs/releases/6.0.1.txt b/docs/releases/6.0.1.txt index 790fa76e99..90158b6ff2 100644 --- a/docs/releases/6.0.1.txt +++ b/docs/releases/6.0.1.txt @@ -27,3 +27,7 @@ Bugfixes * Fixed a visual regression in Django 6.0 for admin form fields grouped under a ``<fieldset>`` in Safari (:ticket:`36807`). + +* Fixed a crash in Django 6.0 caused by infinite recursion when calling + ``repr()`` on an unevaluated ``django.utils.csp.LazyNonce`` instance + (:ticket:`36810`). diff --git a/tests/utils_tests/test_csp.py b/tests/utils_tests/test_csp.py index 86682544e2..c737b59256 100644 --- a/tests/utils_tests/test_csp.py +++ b/tests/utils_tests/test_csp.py @@ -2,7 +2,7 @@ from secrets import token_urlsafe from unittest.mock import patch from django.test import SimpleTestCase -from django.utils.csp import CSP, LazyNonce, build_policy +from django.utils.csp import CSP, LazyNonce, build_policy, generate_nonce from django.utils.functional import empty basic_config = { @@ -155,6 +155,7 @@ class LazyNonceTests(SimpleTestCase): self.assertTrue(nonce) self.assertEqual(nonce, val) self.assertIsInstance(nonce, str) + self.assertEqual(repr(nonce), f"<LazyNonce: '{nonce}'>") self.assertEqual(len(val), 22) # Based on secrets.token_urlsafe of 16 bytes. self.assertEqual(generated_tokens, [nonce]) # Also test the wrapped value. @@ -166,3 +167,10 @@ class LazyNonceTests(SimpleTestCase): second = str(nonce) self.assertEqual(first, second) + + def test_repr(self): + nonce = LazyNonce() + self.assertEqual(repr(nonce), f"<LazyNonce: {repr(generate_nonce)}>") + + str(nonce) # Force nonce generation. + self.assertRegex(repr(nonce), r"<LazyNonce: '[^']+'>") |
