]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-132002: Fix crash of `ContextVar` on unhashable `str` subtype (GH-132003...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 2 Apr 2025 12:05:30 +0000 (14:05 +0200)
committerGitHub <noreply@github.com>
Wed, 2 Apr 2025 12:05:30 +0000 (12:05 +0000)
gh-132002: Fix crash of `ContextVar` on unhashable `str` subtype (GH-132003)
(cherry picked from commit ab2a3dda1d3b6668162a847bf5b6aca2855a3416)

Co-authored-by: sobolevn <mail@sobolevn.me>
Lib/test/test_context.py
Misc/NEWS.d/next/Library/2025-04-02-11-31-15.gh-issue-132002.TMsYvE.rst [new file with mode: 0644]
Python/context.c

index dc6856509a40a01a85ec628bba165f545119499e..e8e5b76ced90eab1229d68a99127a88d1e91f861 100644 (file)
@@ -83,6 +83,15 @@ class ContextTest(unittest.TestCase):
             contextvars.Context(a=1)
         contextvars.Context(**{})
 
+    def test_context_new_unhashable_str_subclass(self):
+        # gh-132002: it used to crash on unhashable str subtypes.
+        class weird_str(str):
+            def __eq__(self, other):
+                pass
+
+        with self.assertRaisesRegex(TypeError, 'unhashable type'):
+            contextvars.ContextVar(weird_str())
+
     def test_context_typerrors_1(self):
         ctx = contextvars.Context()
 
diff --git a/Misc/NEWS.d/next/Library/2025-04-02-11-31-15.gh-issue-132002.TMsYvE.rst b/Misc/NEWS.d/next/Library/2025-04-02-11-31-15.gh-issue-132002.TMsYvE.rst
new file mode 100644 (file)
index 0000000..b46bc25
--- /dev/null
@@ -0,0 +1,2 @@
+Fix crash when deallocating :class:`contextvars.ContextVar` with weird
+unahashable string names.
index 7bccfad11a45b1f8395248b8e92ce72061b6a3ab..e5899219daac8c934bbb6c328885ea158cbd8cc7 100644 (file)
@@ -821,20 +821,19 @@ contextvar_new(PyObject *name, PyObject *def)
         return NULL;
     }
 
-    var->var_hash = contextvar_generate_hash(var, name);
-    if (var->var_hash == -1) {
-        Py_DECREF(var);
-        return NULL;
-    }
-
     var->var_name = Py_NewRef(name);
-
     var->var_default = Py_XNewRef(def);
 
     var->var_cached = NULL;
     var->var_cached_tsid = 0;
     var->var_cached_tsver = 0;
 
+    var->var_hash = contextvar_generate_hash(var, name);
+    if (var->var_hash == -1) {
+        Py_DECREF(var);
+        return NULL;
+    }
+
     if (_PyObject_GC_MAY_BE_TRACKED(name) ||
             (def != NULL && _PyObject_GC_MAY_BE_TRACKED(def)))
     {