]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-42266: Handle monkey-patching descriptors in LOAD_ATTR cache (GH-23157)
authorPablo Galindo <Pablogsal@gmail.com>
Thu, 5 Nov 2020 09:23:15 +0000 (09:23 +0000)
committerGitHub <noreply@github.com>
Thu, 5 Nov 2020 09:23:15 +0000 (09:23 +0000)
Lib/test/test_opcache.py [new file with mode: 0644]
Misc/NEWS.d/next/Core and Builtins/2020-11-04-23-03-25.bpo-42266.G4hGDe.rst [new file with mode: 0644]
PCbuild/lib.pyproj
Python/ceval.c

diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py
new file mode 100644 (file)
index 0000000..61f337d
--- /dev/null
@@ -0,0 +1,23 @@
+import unittest
+
+class TestLoadAttrCache(unittest.TestCase):
+    def test_descriptor_added_after_optimization(self):
+        class Descriptor:
+            pass
+
+        class C:
+            def __init__(self):
+                self.x = 1
+            x = Descriptor()
+
+        def f(o):
+            return o.x
+
+        o = C()
+        for i in range(1025):
+            assert f(o) == 1
+
+        Descriptor.__get__ = lambda self, instance, value: 2
+        Descriptor.__set__ = lambda *args: None
+
+        self.assertEqual(f(o), 2)
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-11-04-23-03-25.bpo-42266.G4hGDe.rst b/Misc/NEWS.d/next/Core and Builtins/2020-11-04-23-03-25.bpo-42266.G4hGDe.rst
new file mode 100644 (file)
index 0000000..a8598cf
--- /dev/null
@@ -0,0 +1,3 @@
+Fixed a bug with the LOAD_ATTR opcode cache that was not respecting
+monkey-patching a class-level attribute to make it a descriptor. Patch by
+Pablo Galindo.
index a15165d92ef1251d7213ce198eaf02fde781e12f..1be60b1a11b9311c3397d05b17195929927e43da 100644 (file)
     <Compile Include="test\test_nntplib.py" />
     <Compile Include="test\test_ntpath.py" />
     <Compile Include="test\test_numeric_tower.py" />
+    <Compile Include="test\test_opcache.py" />
     <Compile Include="test\test_opcodes.py" />
     <Compile Include="test\test_openpty.py" />
     <Compile Include="test\test_operator.py" />
index 13b209fc706b6cf5b5725bfe1bc6407a696b124f..32e3019682f0ae07a44b68fc845cc62c242acc98 100644 (file)
@@ -3179,7 +3179,6 @@ main_loop:
                 if (co_opcache != NULL && /* co_opcache can be NULL after a DEOPT() call. */
                     type->tp_getattro == PyObject_GenericGetAttr)
                 {
-                    PyObject *descr;
                     Py_ssize_t ret;
 
                     if (type->tp_dictoffset > 0) {
@@ -3190,12 +3189,7 @@ main_loop:
                                 goto error;
                             }
                         }
-
-                        descr = _PyType_Lookup(type, name);
-                        if (descr == NULL ||
-                            Py_TYPE(descr)->tp_descr_get == NULL ||
-                            !PyDescr_IsData(descr))
-                        {
+                        if (_PyType_Lookup(type, name) == NULL) {
                             dictptr = (PyObject **) ((char *)owner + type->tp_dictoffset);
                             dict = *dictptr;