]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-44523: Remove the pass-through for hash() in weakref proxy objects (GH-26950...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 29 Jun 2021 23:19:32 +0000 (16:19 -0700)
committerGitHub <noreply@github.com>
Tue, 29 Jun 2021 23:19:32 +0000 (00:19 +0100)
(cherry picked from commit e2fea101fd5517f33371b04432842b971021c3bf)

Co-authored-by: Pablo Galindo <Pablogsal@gmail.com>
Lib/test/test_weakref.py
Misc/NEWS.d/next/Core and Builtins/2021-06-29-11-49-29.bpo-44523.67-ZIP.rst [new file with mode: 0644]
Objects/weakrefobject.c

index 56a42f055d0b5491337652a2825a93458549b893..dd5a781ed59d8ba87939b50232d0b2af011c3188 100644 (file)
@@ -422,14 +422,20 @@ class ReferencesTestCase(TestBase):
         self.assertEqual("".join(reversed(weakref.proxy(obj))), "cba")
 
     def test_proxy_hash(self):
-        cool_hash = 299_792_458
-
         class MyObj:
             def __hash__(self):
-                return cool_hash
+                return 42
+
+        obj = MyObj()
+        with self.assertRaises(TypeError):
+            hash(weakref.proxy(obj))
+
+        class MyObj:
+            __hash__ = None
 
         obj = MyObj()
-        self.assertEqual(hash(weakref.proxy(obj)), cool_hash)
+        with self.assertRaises(TypeError):
+            hash(weakref.proxy(obj))
 
     def test_getweakrefcount(self):
         o = C()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-06-29-11-49-29.bpo-44523.67-ZIP.rst b/Misc/NEWS.d/next/Core and Builtins/2021-06-29-11-49-29.bpo-44523.67-ZIP.rst
new file mode 100644 (file)
index 0000000..aa51a74
--- /dev/null
@@ -0,0 +1,3 @@
+Remove the pass-through for :func:`hash` of :class:`weakref.proxy` objects
+to prevent unintended consequences when the original referred object
+dies while the proxy is part of a hashable object. Patch by Pablo Galindo.
index 313e8abab5a25fe47d06670caa9eee1bc936ab6e..c36d2395cc8c53901635dab012e3355bfe097cd3 100644 (file)
@@ -732,21 +732,6 @@ static PyMappingMethods proxy_as_mapping = {
 };
 
 
-static Py_hash_t
-proxy_hash(PyObject *self)
-{
-    PyWeakReference *proxy = (PyWeakReference *)self;
-    if (!proxy_checkref(proxy)) {
-        return -1;
-    }
-    PyObject *obj = PyWeakref_GET_OBJECT(proxy);
-    Py_INCREF(obj);
-    Py_hash_t res = PyObject_Hash(obj);
-    Py_DECREF(obj);
-    return res;
-}
-
-
 PyTypeObject
 _PyWeakref_ProxyType = {
     PyVarObject_HEAD_INIT(&PyType_Type, 0)
@@ -763,7 +748,8 @@ _PyWeakref_ProxyType = {
     &proxy_as_number,                   /* tp_as_number */
     &proxy_as_sequence,                 /* tp_as_sequence */
     &proxy_as_mapping,                  /* tp_as_mapping */
-    proxy_hash,                         /* tp_hash */
+// Notice that tp_hash is intentionally omitted as proxies are "mutable" (when the reference dies).
+    0,                                  /* tp_hash */
     0,                                  /* tp_call */
     proxy_str,                          /* tp_str */
     proxy_getattr,                      /* tp_getattro */