]> granicus.if.org Git - python/commitdiff
bpo-37619: update_one_slot() should not ignore wrapper descriptors for wrong type...
authorJeroen Demeyer <J.Demeyer@UGent.be>
Tue, 10 Sep 2019 11:21:57 +0000 (13:21 +0200)
committerT. Wouters <thomas@python.org>
Tue, 10 Sep 2019 11:21:57 +0000 (04:21 -0700)
Lib/test/test_descr.py
Misc/NEWS.d/next/Core and Builtins/2019-07-18-11-50-49.bpo-37619.X6Lulo.rst [new file with mode: 0644]
Objects/typeobject.c

index 4368bb585f319f4ae9e60713866ea18ae0cf12ed..796e60a770479542cc8f87f161ad067a55ca1d20 100644 (file)
@@ -4649,6 +4649,18 @@ order (MRO) for bases """
         self.assertEqual(x["y"], 42)
         self.assertEqual(x, -x)
 
+    def test_wrong_class_slot_wrapper(self):
+        # Check bpo-37619: a wrapper descriptor taken from the wrong class
+        # should raise an exception instead of silently being ignored
+        class A(int):
+            __eq__ = str.__eq__
+            __add__ = str.__add__
+        a = A()
+        with self.assertRaises(TypeError):
+            a == a
+        with self.assertRaises(TypeError):
+            a + a
+
     def test_slot_shadows_class_variable(self):
         with self.assertRaises(ValueError) as cm:
             class X:
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-07-18-11-50-49.bpo-37619.X6Lulo.rst b/Misc/NEWS.d/next/Core and Builtins/2019-07-18-11-50-49.bpo-37619.X6Lulo.rst
new file mode 100644 (file)
index 0000000..8723d3d
--- /dev/null
@@ -0,0 +1,3 @@
+When adding a wrapper descriptor from one class to a different class
+(for example, setting ``__add__ = str.__add__`` on an ``int`` subclass),
+an exception is correctly raised when the operator is called.
index 71d7f6f0e5c5c593b609c08dd49c64d52337353a..883bc22bbde1be64a1570c0e0222b028286e41fa 100644 (file)
@@ -7307,14 +7307,21 @@ update_one_slot(PyTypeObject *type, slotdef *p)
             if (tptr == NULL || tptr == ptr)
                 generic = p->function;
             d = (PyWrapperDescrObject *)descr;
-            if (d->d_base->wrapper == p->wrapper &&
+            if ((specific == NULL || specific == d->d_wrapped) &&
+                d->d_base->wrapper == p->wrapper &&
                 PyType_IsSubtype(type, PyDescr_TYPE(d)))
             {
-                if (specific == NULL ||
-                    specific == d->d_wrapped)
-                    specific = d->d_wrapped;
-                else
-                    use_generic = 1;
+                specific = d->d_wrapped;
+            }
+            else {
+                /* We cannot use the specific slot function because either
+                   - it is not unique: there are multiple methods for this
+                     slot and they conflict
+                   - the signature is wrong (as checked by the ->wrapper
+                     comparison above)
+                   - it's wrapping the wrong class
+                 */
+                use_generic = 1;
             }
         }
         else if (Py_TYPE(descr) == &PyCFunction_Type &&