summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Reed <sean@sean-reed.com>2025-12-19 22:09:25 +0100
committerNatalia <124304+nessita@users.noreply.github.com>2025-12-24 14:48:16 -0300
commit16107ab710dc23d5ea0aa17da6bf29fe89b61bb0 (patch)
treef9d3376b3cb66d1c309b6578dbaf54126960ec4b
parent774543ed4feb37916071e81c0d0b81ba514333fa (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.py9
-rw-r--r--docs/releases/6.0.1.txt4
-rw-r--r--tests/utils_tests/test_csp.py10
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: '[^']+'>")